map = {
const height = 600;
const projection = d3.geoMercator().fitExtent(
[
[1, 10],
[width - 50, height - 10]
],
japan
);
const path = d3.geoPath(projection);
const [[, top], [, bottom]] = path.bounds(japan);
const f = (d) => bottom + (top - bottom) * J(d);
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("width", width);
const clip = svg
.append("clipPath")
.attr("id", "clip")
.append("path")
.attr("d", path(japan));
svg
.append("g")
.selectAll()
.data(d3.ticks(0, 1, 50))
.join("line")
.attr("x2", width - 50)
.attr("stroke", "black")
.attr("stroke-width", (d) => ((d * 10) % 1 ? 0.25 : 1))
.attr("transform", (d) => `translate(0,${f(d)})`);
svg
.append("g")
.selectAll()
.data(d3.ticks(0, 1, 10))
.join("text")
.attr("font-family", "sans-serif")
.attr("font-size", "12")
.attr("transform", (d) => `translate(${width - 2},${f(d)})`)
.attr("y", "0.38em")
.attr("text-anchor", "end")
.text((d) => `${(100 * d) | 0}%`);
svg
.append("path")
.attr("stroke", "none")
.attr("fill", "beige")
.attr("fill-opacity", 0.85)
.attr("d", path(japan));
const bg = svg
.append("rect")
.attr("clip-path", "url(#clip)")
.attr("width", width)
.attr("height", height)
.attr("stroke", "none")
.attr("fill", "#BC002D");
svg
.append("path")
.attr("stroke", "black")
.attr("fill", "none")
.attr("d", path(japan));
function update(percentage) {
const r = f(percentage);
bg.attr("y", r);
return r;
}
return Object.assign(svg.node(), { update });
}