Javascript 小型多折线图的独立比例尺
我正在使用Observable上的d3.v5制作一个小型多折线图,数据集的结构如下: 对于可视化,y比例从域的Javascript 小型多折线图的独立比例尺,javascript,d3.js,observablehq,Javascript,D3.js,Observablehq,我正在使用Observable上的d3.v5制作一个小型多折线图,数据集的结构如下: 对于可视化,y比例从域的值数组中获取num。有几行具有唯一的键值,我想用它们来生成小倍数。上图显示了第一个键 在可视化小倍数后,我注意到所有的折线图都使用相同的y刻度,这不是我想要做的。这就是我目前拥有的: const y_scale=d3 .scaleLinear() .domain([0,d3.max(series,d=>d3.max(d.values,m=>m.num))) .范围([width/2,w
值数组中获取num
。有几行具有唯一的键值,我想用它们来生成小倍数。上图显示了第一个键
在可视化小倍数后,我注意到所有的折线图都使用相同的y刻度,这不是我想要做的。这就是我目前拥有的:
const y_scale=d3
.scaleLinear()
.domain([0,d3.max(series,d=>d3.max(d.values,m=>m.num)))
.范围([width/2,width/2-起始y-边距.bottom]);
是否有一种方法可以调整域,使每个图表根据其自己的num
值具有自己的比例
编辑1:在顶部添加笔记本链接这里惯用的D3解决方案将使用。然而,有几种不同的工作备选方案
对于使用局部变量,我们首先声明它们
const localScale = d3.local();
const localLine = d3.local();
然后,我们在“输入”选项中设置不同的比例:
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();
}
谢谢,成功了!有没有一种方法可以对圆进行同样的处理?我尝试使用相同的方法附加多个圆,但我不确定如何在.set
函数中设置其属性。只需在.attr(“cy”,函数(d){…})
中获取y刻度的局部变量即可。