Published
Edited
Apr 27, 2022
1 star
Insert cell
# World Stadium Location Visualization Tutorial
'' https://observablehq.com/@figurescc/stadiums-around-the-world-step-by-step
''
Insert cell
html`
<div style="
width: 100px;
height: 100px;
background-color: #eee;"
/>
`
Insert cell
html`
<svg viewbox="0 0 100 100" width="100px">
<rect x="0" y="0" width="100" height="100" fill="#eee" />
</svg>
`
Insert cell
html`
<svg viewbox="0 0 100 100" width="100px">
<rect x="0" y="0" width="100" height="100" fill="#eee" />
<path d="M 10,10 L 90,50 L 10,90 Z" stroke="black" fill="none" />
</svg>
`
Insert cell
d3 = require("d3")
Insert cell
countries = d3.json("https://gist.githubusercontent.com/phil-pedruco/10447085/raw/426fb47f0a6793776a044f17e66d17cbbf8061ad/countries.geo.json")
Insert cell
height = width /2
Insert cell
{
const projection = d3.geoMercator(); // we choose the infamous mercator for starters
const path = d3.geoPath(projection); // a path generator using our projection method

console.log(path(countries)); // check the console to see how the path generator transforms
// the geoJSON into SVG path drawing commands
return html`
<svg viewbox="0 0 ${width} ${height}">
<path d="${path(countries)}" stroke="#515150" fill="#343332" />
</svg>
`;
}
Insert cell
{
const projection = d3.geoMercator();
const path = d3.geoPath(projection);
const center = [13.064458, 52.382106]; // our current location
const position = projection(center); // the projection method will turn longitude,latitude into x,y
return html`
<svg viewbox="0 0 ${width} ${height}">
<path d="${path(countries)}" stroke="#515150" fill="#343332" />
<circle cx="${position[0]}" cy="${position[1]}" r="10" fill="royalblue" opacity="0.5" />
</svg>
`;
}
Insert cell
stadiumDataRaw = d3.csv("https://gist.githubusercontent.com/davidelsche/b25f9373135bf9c3ab14e526626423b4/raw/779156c1145bcf09a1356c7ef6f4fa5daa635aa6/world_of_stadiums.csv", d => {
return {
country: d.country,
capacity: +d.capacity, // the plus operator will interpret all entries for that column as numbers
lat: +d.lat,
long: +d.long,
kind: d.kind,
city: d.city,
name: d.name,
}
})
Insert cell
{
const projection = d3.geoMercator();
const path = d3.geoPath(projection);
const circles = stadiumDataRaw.map(d => {
const position = projection([d.long, d.lat]);
const [x, y] = position;
const type = d.kind.replace(" ", "").toLowerCase();
const circle = svg`<circle cx="${x}" cy="${y}" r="5" fill="royalblue" opacity="0.1" />`;
return circle;
});

return html`
<svg viewbox="0 0 ${width} ${height}">
<path d="${path(countries)}" stroke="#515150" fill="#343332" />
${circles}
</svg>
`;
}
Insert cell
stadiumColors = ({
baseball: "#8339FF",
basketball: "#169B78",
bullfight: "#EA3086",
cricket: "#AAC80B",
football: "#0097DB",
hockey: "#FFA930",
horseracing: "#8EC7F3",
other: "#FFA3F0",
race: "#D25E69",
rugby: "#FFD110",
})
Insert cell
{
const projection = d3.geoNaturalEarth1();
const path = d3.geoPath(projection);
// we need to know what the biggest value is in the dataset
const maxCapacity = d3.max(stadiumDataRaw, o => o.capacity);
// the biggest value will have a radius of 6, all others will be scaled accordingly
const circleScale = d3.scaleSqrt()
.domain([0, maxCapacity])
.range([0, 6]);
const circles = stadiumDataRaw.map(d => {
const position = projection([d.long, d.lat]);
const [x, y] = position;
const type = d.kind.replace(" ", "").toLowerCase();
return svg`<circle cx="${x}" cy="${y}" r="${circleScale(d.capacity)}" fill="${stadiumColors[type]}" opacity="0.8" />`;
});

// d3.geoGraticule10 is a utiliy function to generate a grid line at every 10 lat/long coordinates
return html`
<svg viewbox="0 0 ${width} ${height}">
<rect x="0" y="0" width="${width}" height="${height}" fill="#191A1A" />
<path d="${path(d3.geoGraticule10())}" stroke="#515150" fill="none" opacity="0.3" />
<path d="${path(countries)}" stroke="#515150" fill="#343332" />
${circles}
</svg>
`;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more