chart = () => {
const wrapper = d3.create("div");
wrapper.append("style").html(css);
const chart = wrapper.selectAll(".chart")
.data(data)
.join("div")
.attr("class", "chart");
const title = chart.append("div")
.attr("class", "title")
.html(d => titles[d.prop]);
const svg = chart.append("svg");
const g = svg.append("g");
const xaxis = g.append("g")
.attr("class", "axis x-axis");
const yaxis = g.append("g")
.attr("class", "axis y-axis");
const bar = g.append("g")
.attr("class", "bars")
.selectAll(".bar")
.data(d => d.data)
.join("rect")
.attr("class", "bar");
return Object.assign(wrapper.node(), {
resize(ww) {
const cols = ww <= 480 ? 1 : 2;
const rows = data.length / cols;
const padInner = 24;
const padTotal = padInner * (cols - 1);
const pad = padTotal / cols;
const r = ww <= 400 ? 3 : 4;
const margin = { left: 38, right: 14, top: 7, bottom: 23 }
const chartMarginBottom = 24;
const basewidth = ww / cols - pad;
const width = basewidth - margin.left - margin.right;
const maxHeight = ww <= 480 ? 100 : 250;
const height = Math.min(basewidth * 9 / 16, maxHeight) - margin.top - margin.bottom;
x.range([0, width]);
props.forEach(prop => {
Y[prop].range([height, 0]);
});
chart
.style("margin-bottom", (_, i) => 1 + Math.floor(i / cols) === rows ? "0px" : `${chartMarginBottom}px`)
.style("margin-left", (_, i) => i % cols === 0 ? "0px" : `${padInner / 2}px`)
.style("margin-right", (_, i) => i % cols === (cols - 1) ? "0px" : `${padInner / 2}px`)
.style("width", `calc(${100 / cols}% - ${pad}px)`)
svg
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
g
.attr("transform", `translate(${[margin.left, margin.top]})`);
xaxis
.attr("transform", `translate(0, ${height})`)
.call(g => xAxisGenerator(g, height));
yaxis
.attr("transform", `translate(${width})`)
.each((d, i, e) => {
d3.select(e[i]).call(g => yAxisGenerator(g, d.prop, width, Y))
});
bar
.attr("height", d => height - Y[d.prop](d.value))
.attr("width", x.bandwidth())
.attr("x", d => x(d.year))
.attr("y", d => Y[d.prop](d.value));
}
})
}