chart = {
const width = 975;
const height = 550;
const zoom = d3.zoom()
.scaleExtent([1, 4])
.on("zoom", zoomed);
const root = d3.create("div")
.attr("class", "root");
const svg = root.append("svg")
.attr("viewBox", [0, -20, width, height])
.on("click", reset);
const g = svg.append("g");
const projection = d3
.geoAlbersUsa()
.fitSize(
[width, height],
topojson.feature(maryland, maryland.objects.Maryland_Counties)
);
const tooltip = root
.append("div")
.attr("class", "cooltip");
const path = d3.geoPath().projection(projection);
svg.append("g")
.attr("transform", "translate(20,35)")
.append(() => legend({
color: d3.scaleSequential([extent[0], extent[1]], d3.interpolatePurples),
title: "Total tests per 100,000",
width: 300
}));
g.append("g")
.attr("cursor", "pointer")
.attr("stroke", "grey")
.attr("stroke-width", 0.75)
.selectAll("path")
.data(
topojson.feature(maryland, maryland.objects.Maryland_Counties).features
)
.join("path")
.attr("fill", d => color(mdcases.get(d.properties.FIPS)))
.on("click", clicked)
.attr("d", path)
.on('mouseover', function(d) {
this.classList.add('hovered');
d3.select(this)
.attr("stroke", "black")
.attr("stroke-width", 3)
.raise();
tooltip.style('display', '');
let node = tooltip.node();
node.innerHTML = "";
node.appendChild(getTooltipContents(d));
})
.on('mousemove', function() {
const rootBounds = root.node().getBoundingClientRect();
const mouseX = d3.event.pageX - rootBounds.left;
const mouseY = d3.event.pageY - rootBounds.top;
tooltip
.style('top', Math.min((mouseY - 10), root.node().offsetHeight - 155) + 'px')
.style('left', (mouseX + 165 <= root.node().offsetWidth ? (mouseX + 10) : (mouseX - 185)) + 'px')
.style('display', 'block')
})
.on('mouseout', function() {
this.classList.remove('hovered');
d3.select(this)
.attr("stroke", null)
.attr("stroke-width", 1)
.lower();
tooltip.style('display', 'none');
});
svg.call(zoom);
function reset() {
svg
.transition()
.duration(750)
.call(
zoom.transform,
d3.zoomIdentity,
d3.zoomTransform(svg.node()).invert([width / 2, height / 2])
);
}
function clicked(d) {
const [[x0, y0], [x1, y1]] = path.bounds(d);
d3.event.stopPropagation();
svg
.transition()
.duration(750)
.call(
zoom.transform,
d3.zoomIdentity
.translate(width / 2, height / 2)
.scale(
Math.min(3, 0.9 / Math.max((x1 - x0) / width, (y1 - y0) / height))
)
.translate(-(x0 + x1) / 2, -(y0 + y1) / 2),
d3.mouse(svg.node())
);
}
function zoomed() {
const { transform } = d3.event;
g.attr("transform", transform);
g.attr("stroke-width", 1 / transform.k);
}
window.addEventListener("resize", () => resized(width, root, svg));
setTimeout(() => resized(width, root, svg), 12);
return root.node();
}