function make_map(opts = {}) {
let { max_size = 900, link_chart = null } = opts;
let map_width = width < max_size ? width : max_size;
let height = 0.575 * map_width;
let div = d3
.create("div")
.style("width", `${map_width}px`)
.style("height", `${height}px`)
.style("overflow", "hidden")
.style("position", "relative");
let svg = div
.append("svg")
.style("overflow", "hidden")
.attr("viewBox", [0, 0, map_width, height]);
let proj = d3
.geoIdentity()
.reflectY(true)
.fitSize([map_width, height], stateTiles);
let path = d3.geoPath().projection(proj);
let map = svg.append("g");
let density_map = new Map();
map
.selectAll("path.tile")
.data(stateTiles.features)
.join("path")
.attr("class", "tile")
.attr("data-fips", (o) => o.properties.fips)
.attr("data-name", (o) => o.properties.name)
.attr("data-abbr", (o) => o.properties.abbr)
.attr("data-rrs", function (d) {
let fd = data.filter((o) => o.abbr == d.properties.abbr);
if (fd.length > 0) {
return fd[0].rr_score;
} else {
return "NA";
}
})
.attr("data-covariate", function (d) {
if (covariate != "---") {
let fd = filtered_data.filter((o) => o.abbr == d.properties.abbr);
if (fd.length > 0) {
return fd[0][covariate];
} else {
return "NA";
}
}
})
.attr("d", path)
.attr("fill", (o) =>
covariate == "---"
? rr_shade(o.properties.abbr)
: state_color(o.properties.abbr)
)
.attr("stroke-width", 0.8)
.attr("stroke", "white")
.attr("stroke-linejoin", "round")
// .on("touchmove", (e) => e.preventDefault())
.on("pointerenter mouseenter", function (evt, o) {
evt.preventDefault();
if (covariate != "---") {
let class_selector = ".color" + state_color(o.properties.abbr).slice(1);
legend
.select(class_selector)
.attr("stroke", "black")
.attr("stroke-width", 2)
.raise();
if (link_chart) {
let selected_circles = d3
.select(link_chart)
.select(`#${o.properties.abbr}`)
.attr("fill", "yellow")
.attr("stroke", "black")
.attr("r", 0.005 * width)
.raise();
}
} else {
if (link_chart) {
d3.select(link_chart)
.select(`.${o.properties.abbr}`)
.attr("stroke", "black")
.attr("stroke-width", 0.002 * width)
.raise();
d3.select(link_chart).select();
}
}
})
.on("mouseout", function (evt, o) {
if (covariate != "---") {
let class_selector = ".color" + state_color(o.properties.abbr).slice(1);
legend
.select(class_selector)
.attr("stroke", "white")
.attr("stroke-width", 0.5);
if (link_chart) {
let selected_circles = d3
.select(link_chart)
.select(`#${o.properties.abbr}`)
.attr("fill", "black")
.attr("r", 0.002 * width);
}
} else {
if (link_chart) {
d3.select(link_chart)
.select(`.${o.properties.abbr}`)
.attr("stroke", null);
}
}
});
map
.selectAll("text")
.data(stateTiles.features)
.join("text")
.text((o) => o.properties.abbr)
.attr("font-size", `${0.022 * map_width}px`)
.attr("x", function (o) {
return path.centroid(o)[0];
})
.attr("text-anchor", "middle")
.attr("y", function (o) {
return path.centroid(o)[1];
})
.attr("dy", 0.008 * map_width)
.attr("pointer-events", "none");
map
.selectAll("path.tile")
.nodes()
.forEach(function (t) {
let content = html`<div>
<div style="font-weight:bold">${t.getAttribute("data-name")}</div>
<div>reproductive rights score: ${t.getAttribute("data-rrs")}</div>
${
covariate != "---"
? `<div>${covariate.replace(/_/g, " ")}: ${d3.format("0.2f")(
t.getAttribute("data-covariate")
)}</div>`
: ""
}
</div>`;
tippy(t, {
content: content,
theme: "light-border",
maxWidth: 500
});
});
let s = map_width / 10;
let legend = svg
.append("g")
.attr("transform", `translate(${map_width - 1.5 * s},${height - 1.2 * s})`);
let arrow_group = legend.append("g");
arrow_group // from http://thenewcode.com/1068/Making-Arrows-in-SVG
.append("svg:defs")
.append("marker")
.attr("id", "arrowhead")
.attr("markerWidth", 0.5 * 10)
.attr("markerHeight", 0.5 * 7)
.attr("refX", 0)
.attr("refY", 0.5 * 3.5)
.attr("orient", "auto")
.append("polygon")
// .attr("points", `0 0, 10 3.5, 0 7`);
.attr("points", `0 0, ${0.5 * 10} ${0.5 * 3.5}, 0 ${0.5 * 7}`);
let patches = legend.append("g");
let arrows = legend.append("g");
if (covariate != "---") {
let n = 5;
let dd = s / n;
let to_rr = d3
.scaleLinear()
.domain([0, n - 1])
.range([rr_scores.min, rr_scores.max]);
let to_covariate = d3
.scaleLinear()
.domain([0, n - 1])
.range([covariate_values.min, covariate_values.max]);
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
patches
.append("rect")
.attr(
"class",
"color" + color(to_rr(i), to_covariate(n - j - 1)).slice(1)
)
.attr("x", i * dd)
.attr("y", j * dd)
.attr("width", s / n)
.attr("height", s / n)
.attr("fill", color(to_rr(i), to_covariate(n - j - 1)))
.attr("stroke", "white")
.attr("stroke-width", 0.5);
}
}
arrows
.append("line")
.attr("x1", 0)
.attr("x2", s)
.attr("y1", s)
.attr("y2", s)
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("marker-end", "url(#arrowhead)");
arrows
.append("line")
.attr("x1", 0)
.attr("x2", 0)
.attr("y1", s)
.attr("y2", 0)
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("marker-end", "url(#arrowhead)");
arrows
.append("text")
.attr("x", 0.15 * s)
.attr("y", 1.2 * s)
.attr("font-size", 0.011 * width)
.text("rr-score");
arrows
.append("text")
.attr("x", -0.016 * width)
.attr("y", -0.012 * width)
.attr("font-size", 0.011 * width)
.text("covariate");
} else {
legend = Legend(
d3.scaleSequential(d3.interpolateRdBu).domain(rr_score_extent),
{
title: "rr-score",
tickFormat: ".0f"
}
);
d3.select(legend).selectAll("text").attr("font-size", "16px");
svg
.append("g")
.attr("transform", `translate(${0.3 * map_width},${0.05 * height})`)
.append("g")
.attr("transform", `scale(${max_size / 700})`)
.append(() => legend);
}
return div.node();
}