map = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height + 60])
.style("font", "10px sans-serif");
const legend = svg
.append("g")
.attr("class", "legendGroup")
.selectAll("g")
.data(legendLines)
.join("g")
.attr(
"transform",
(d, i) =>
`translate(${legendSizes.x0},${
legendSizes.y0 + i * legendSizes.spacingY
})`
);
legend
.append("line")
.attr("class", (d) => d.class)
.attr("stroke-width", 4)
.attr("stroke", (d) => d.color)
.attr("y1", (_d, i) => legendSizes.y0 + i * legendSizes.spacingY)
.attr("y2", (_d, i) => legendSizes.y0 + i * legendSizes.spacingY)
.attr("x1", legendSizes.x0)
.attr("x2", legendSizes.spacingX);
legend
.append("text")
.attr("x", legendSizes.spacingX + 5)
.attr("y", (d, i) => legendSizes.y0 + legendSizes.spacingY * i + 5)
.attr("class", "label")
.text((d) => d.name);
/* Areas */
const buurt = svg
.append("g")
.attr("class", "buurtGroup")
.selectAll("g")
.data(stadsdelen)
.join("g");
buurt
.append("path")
.attr("d", path)
.attr("class", "buurt")
.attr("fill", (d) => colorScaleStadsdelen(d.properties.Stadsdeel_code));
buurt
.append("title")
.text(
(d) =>
`${stadsdeel[d.properties.Stadsdeel_code]}: ${
d.properties.Buurtcombinatie
}`
);
// Draw borders around buurten
buurt
.append("path")
.attr(
"d",
path(topojson.mesh(buurten, buurten.objects.buurten, (a, b) => a !== b))
)
.attr("fill", "none")
.attr("stroke", "#fff")
.attr("stroke-width", 0.4)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("pointer-events", "none")
.attr("opacity", 0.6);
// Draw borders around stadsdelen
buurt
.append("path")
.attr(
"d",
path(
topojson.mesh(
buurten,
buurten.objects.buurten,
(a, b) => a.properties.Stadsdeel_code !== b.properties.Stadsdeel_code
)
)
)
.attr("fill", "none")
.attr("opacity", 0.3)
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("pointer-events", "none");
/* Lines */
// Get the number of tracks for each line
trammetro.features.forEach(
(d) => (d.properties.nrOftracks = d.properties.Lijn.split(/ \| /g).length)
);
// Draw the tram/metro tracks
const tramMetro = svg
.append("g")
.attr("class", "tramMetroGroup")
.selectAll("g")
.data(trammetro.features)
.join("g");
tramMetro
.selectAll("path")
// Duplicate the lineString feature based on the number of tracks
.data((lineString) =>
d3.range(0, lineString.properties.nrOftracks).map(() => lineString)
)
.join("path")
.attr("fill", "none")
.attr("stroke-linejoin", "round")
.attr("class", (d) => d.properties.Modaliteit.toLowerCase())
.attr("d", (lineString, i) => {
// Offset each lineString by 60 meters
const lineStringOffset = turf.lineOffset(
lineString.geometry,
i * offsetDistance,
{ units: "meters" }
);
return path(lineStringOffset);
})
.attr("stroke", (d, i) => colors.get(d.properties.Lijn.split(/ \| /g)[i]))
.attr("stroke-width", 1.5)
.append("title")
.text(
(d) =>
(d.properties.Lijn.split(" ").length !== 1 ? "Lijnen: " : "Lijn: ") +
d.properties.Lijn
);
// Draw the train tracks
const trainTracks = svg
.append("g")
.attr("id", "trainTracks")
.selectAll("path")
.data(spoorGeo.features);
trainTracks
.join("path")
.attr("fill", "none")
.attr("stroke-linejoin", "round")
.attr("stroke", "#e5e5e5")
.attr("stroke-width", 2.5)
// .attr("opacity", 0.5)
.attr("d", path);
trainTracks
.join("path")
.attr("fill", "none")
.attr("stroke-linejoin", "round")
.attr("stroke", "black")
.attr("stroke-dasharray", 12)
.attr("stroke-width", 2.5)
.attr("opacity", 0.7)
.attr("d", path)
.append("title")
.text("Treinspoor");
/* Points */
// Draw the points for the tram & metro stops
svg
.selectAll(".trammetrostations")
.data(tramMetroStations.features)
.join("circle")
.attr(
"transform",
(d) => `translate(${projection(d.geometry.coordinates)})`
)
.attr("r", 3)
.attr("fill", "white")
.attr("stroke", "#e5e5e5")
.attr("opacity", 0.7)
.append("title")
.text(
({ properties }) =>
`${properties.Modaliteit}halte : Lijn ${properties.Lijn}`
);
// Draw the points for the stations
const station = svg
.append("g")
.attr("class", "stationGroup")
.selectAll("g")
.data(trainstations)
.join("g")
.attr("transform", (d) => `translate(${projection([d.lon, d.lat])})`);
station
.append("circle")
.attr("class", "station")
.attr("fill", "#ffb310")
.attr("r", (d) => (d.intercity === "true" ? 6 : 4))
.attr("stroke", "#092869")
.attr("stroke-width", 2)
.attr("z-index", 3)
.append("title")
.text((d) => `Station ${d.name}`);
station
.append("text")
.text((d) => d.name)
.attr("y", -10)
.attr("class", "stationNaam")
.attr("fill", "black")
.attr("font-size", "1.5em")
.attr("text-anchor", "middle");
yield svg.node();
}