这里惯用的 D3 解决方案是使用局部变量。然而,有几种不同的工作选择。
对于使用局部变量,我们首先声明它们...
const localScale = d3.local();
const localLine = d3.local();
然后,我们在“enter”选择中设置不同的比例:
var enter = my_group
.enter()
.append("g")
.attr("class", "chart_group")
.each(function(d) {
const yScale = localScale.set(this, d3
.scaleLinear()
.domain([0, d3.max(d.values, d => d.num)])
.range([panel_width / 2, panel_width / 2 - start_y - margin]));
localLine.set(this, d3
.line()
.x(d => x_scale(d.date))
.y(d => yScale(d.num)));
});
最后,我们得到了这些尺度:
sub_group
.select(".chart_line")
.attr("d", function(d) {
return localLine.get(this)(d)
})
这是整个单元格,将其复制/粘贴到您的笔记本中,替换您的单元格:
chart = {
const panels_per_row = 4;
const panel_width = (width - margin * 8) / panels_per_row;
const height =
margin + (panel_width + margin) * (parseInt(my_data.length / 2) + 1);
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
const start_x = 2;
const start_y = panel_width / 3 + margin;
const x_scale = d3
.scaleBand()
.domain(d3.set(series[0].values, d => d.date).values())
.range([0, panel_width]);
const localScale = d3.local();
const localLine = d3.local();
//join
var my_group = svg.selectAll('.chart_group').data(series, d => d.key);
//exit and remove
my_group.exit().remove();
//enter new groups
var enter = my_group
.enter()
.append("g")
.attr("class", "chart_group")
.each(function(d) {
const yScale = localScale.set(this, d3
.scaleLinear()
.domain([0, d3.max(d.values, d => d.num)])
.range([panel_width / 2, panel_width / 2 - start_y - margin]));
localLine.set(this, d3
.line()
.x(d => x_scale(d.date))
.y(d => yScale(d.num)));
});
//append elements to new group
enter.append("rect").attr("class", "group_rect");
enter.append("text").attr("class", "group_text");
enter.append("g").attr("class", "sub_chart_group");
//merge
my_group = my_group.merge(enter);
position_group_elements(my_group);
//join
var sub_group = my_group
.select(".sub_chart_group")
.selectAll('.sub_chart_elements_group')
.data(d => [d.values]); // data is wrapped in an array because this is a line/area chart
//exit and remove
sub_group.exit().remove();
//enter new groups
var sub_enter = sub_group
.enter()
.append("g")
.attr("class", "sub_chart_elements_group");
//append elements to new group
sub_enter.append("path").attr("class", "chart_line");
//merge
sub_group = sub_group.merge(sub_enter);
sub_group
.select(".chart_line")
.attr("d", function(d) {
return localLine.get(this)(d)
})
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("transform", "translate(" + start_x + "," + start_y + ")");
function position_group_elements(my_group) {
//position rectangle
my_group
.select(".group_rect")
.attr("x", function(d, i) {
//two groups per row so
var position = i % panels_per_row;
d.x_pos = position * (panel_width + margin) + margin;
d.y_pos =
parseInt(i / panels_per_row) * (panel_width + margin) + margin;
return d.x_pos;
})
.attr("y", d => d.y_pos)
.attr("fill", "#eee")
.attr("stroke", "#aaa")
.attr("stroke-width", 1)
.attr("width", panel_width)
.attr("height", panel_width);
//then position sub groups
my_group
.select(".sub_chart_group")
.attr("id", d => d.key)
.attr("transform", d => "translate(" + d.x_pos + "," + d.y_pos + ")");
}
return svg.node();
}