Published
Edited
Nov 5, 2020
1 fork
1 star
Insert cell
Insert cell
Insert cell
Insert cell
d3[projectionType] + ''
Insert cell
Insert cell
viz = {
// remove previously rendered svg
d3.select('#_svg').remove();

// set up canvas
const wrapper = d3
.select("#wrapper")
.append("svg")
.attr('id', '_svg')
.attr("width", width)
.attr("height", height);

const bounds = wrapper
.append("g")
.style("transform", `translate(${margins.left}px, ${margins.top}px)`);

// draw data
const earth = bounds
.append("path")
.attr("class", "earth")
.attr("d", pathGenerator(sphere));

const graticuleJson = d3.geoGraticule10(); // grids
const graticule = bounds
.append("path")
.attr("class", "graticule")
.attr("d", pathGenerator(graticuleJson));

const countries = bounds
.selectAll(".country")
.data(countryShapes.features)
.enter()
.append("path")
.attr("class", d => ["country", countryIdAccessor(d)].join(" "))
.attr("d", pathGenerator)
.attr("fill", d => {
const metricValue = metricDataByRegion[countryIdAccessor(d)];
if (typeof metricValue == "undefined") return "#e2e6e9";
return colorScale(metricValue);
});

const voronoi = bounds
.selectAll(".voronoi")
.data(countryShapes.features)
.enter()
.append("path")
.attr("class", "voronoi")
.attr("d", (d, i) => voronoiGenerator.renderCell(i));

// draw peripherals
const legendGroup = wrapper
.append("g")
.attr(
"transform",
`translate(${120},${
width < 800 ? boundedHeight - 30 : boundedHeight * 0.5
})`
);

const legendTitle = legendGroup
.append("text")
.attr("y", -23)
.attr("class", "legend-title")
.text("Population growth");

const legendByline = legendGroup
.append("text")
.attr("y", -9)
.attr("class", "legend-byline")
.text("Percent change in 2017");

const defs = wrapper.append("defs");
const legendGradientId = "legend-gradient";
const gradient = defs
.append("linearGradient")
.attr("id", legendGradientId)
.selectAll("stop")
.data(colorScale.range())
.enter()
.append("stop")
.attr("stop-color", d => d)
.attr(
"offset",
(d, i) =>
`${
(i * 100) / 2 // 2 is one less than our array's length
}%`
);

const legendWidth = 120;
const legendHeight = 16;
const legendGradient = legendGroup
.append("rect")
.attr("x", -legendWidth / 2)
.attr("height", legendHeight)
.attr("width", legendWidth)
.style("fill", `url(#${legendGradientId})`);

const legendValueRight = legendGroup
.append("text")
.attr("class", "legend-value")
.attr("x", legendWidth / 2 + 10)
.attr("y", legendHeight / 2)
.text(`${d3.format(".1f")(maxChange)}%`);

const legendValueLeft = legendGroup
.append("text")
.attr("class", "legend-value")
.attr("x", -legendWidth / 2 - 10)
.attr("y", legendHeight / 2)
.text(`${d3.format(".1f")(-maxChange)}%`)
.style("text-anchor", "end");

navigator.geolocation.getCurrentPosition(myPosition => {
const [x, y] = projection([
myPosition.coords.longitude,
myPosition.coords.latitude
]);
const myLocation = bounds
.append("circle")
.attr("class", "my-location")
.attr("cx", x)
.attr("cy", y)
.attr("r", 0)
.transition()
.duration(500)
.attr("r", 10);
});

// set up interactions
voronoi.on("mouseenter", onMouseEnter).on("mouseleave", onMouseLeave);

const tooltip = d3.select("#tooltip");
function onMouseEnter(...args) {
const datum = args[1];
tooltip.style("opacity", 1);

const countryId = countryIdAccessor(datum);
const metricValue = metricDataByRegion[countryId] || 0;

tooltip.select("#country").text(countryNameAccessor(datum));

tooltip.select("#value").text(`${d3.format(",.2f")(metricValue)}%`);

const [centerX, centerY] = pathGenerator.centroid(datum);

const x = centerX + margins.left;
const y = centerY + margins.top;

tooltip.style(
"transform",
`translate(` + `calc( -50% + ${x}px),` + `calc(-100% + ${y}px)` + `)`
);

d3.select(`.${countryId}`).classed("is-hovered", true);
}

function onMouseLeave() {
tooltip.style("opacity", 0);
d3.selectAll(`.country`).classed("is-hovered", false);
}

return `Renders the map`;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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