chart = {
const width = 960;
const height = 600;
const tooltipWidth = 500;
const tooltipHeight = 200;
const projection = d3
.geoAlbersUsa()
.translate([width / 2, height / 2])
.scale([1200]);
const path = d3.geoPath().projection(projection);
const svg = d3.select(DOM.svg(width, height));
svg
.append("path")
.datum(topojson.merge(us, us.objects.lower48.geometries))
.attr("fill", "#f3e9dc")
.attr("stroke", "#c08552")
.attr("d", d3.geoPath());
svg
.append("path")
.datum(topojson.mesh(us, us.objects.lower48, (a, b) => a !== b))
.attr("fill", "none")
.attr("stroke", "#c08552")
.attr("stroke-linejoin", "round")
.attr("d", d3.geoPath());
const g = svg.append("g").attr("fill", "none").attr("stroke", "black");
const tooltip = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0.9)
.style("position", "absolute")
.style("width", tooltipWidth + "px")
.style("height", tooltipHeight + "px")
.style("display", "flex")
.style("align-items", "center")
.style("background", "white")
.style("padding", "10px")
.style("border", "1px solid #ccc")
.style("border-radius", "5px")
.style("pointer-events", "none")
.style("font-size", "0.55em")
.style("color", "black")
.style("box-shadow", "2px 2px 10px rgba(0,0,0,0.5)");
svg
.selectAll("circle")
.data(df)
.enter()
.append("circle")
.attr("cx", (d) => projection([d.longitude, d.latitude])[0])
.attr("cy", (d) => projection([d.longitude, d.latitude])[1])
.attr("r", 8)
.attr("opacity", 0.5)
.attr("fill", "#8B4513")
.attr("stroke", "black")
.on("mouseover", (event, d) => {
const xOffset =
event.pageX + tooltipWidth + 20 > window.innerWidth
? -tooltipWidth - 20
: 10;
tooltip.transition().duration(200).style("opacity", 0.9);
tooltip
.html(
`<div style="height: 100%; display: flex; justify-content: start;">
<img src="${d.image}" alt="${d.name}" style="max-width: 50%; max-height: 100%; margin-right: 10px;">
<div>
<strong>${d.name}</strong><br/>
${d.description}
</div>
</div>`
)
.style("left", event.pageX + xOffset + "px")
.style("top", event.pageY - tooltipHeight / 2 + "px");
})
.on("mouseout", () => {
tooltip.transition().duration(500).style("opacity", 0);
});
return svg.node();
}