在多个图表上组合 elasticY

Combined elasticY over multiple charts

我想通过函数设置条形图的轴,但在 elasticY() 语法之外。这里的用例是我在同一个 dimension/group 中有两个条形图,如下所示:

chart1
.dimension(dim).group(gr)
.valueAccessor(d => d.value.one)
.elasticY()

chart1
.dimension(dim).group(gr)
.valueAccessor(d => d.value.two)
.elasticY()

这些工作,但 elasticY() 单独设置域,这意味着两个图表的轴不对齐。我可以设置 .y(d3.scaleLinear().domain([0,100])) 但这会使图表成为静态的。我更愿意做的是:

.valueAccessor(function(d) {
result = func(d)// function to return the max of value.one and value.two
chart1.y().domain([0, result])
return d.value.one;
}

但这似乎不起作用。

.elasticY(true) 使图表在每次绘制图表时计算最小值和最大值,并将它们应用于 Y 刻度的域。

如果您想要更复杂的行为,您可以设置 elasticY(false) 并添加 preRenderpreRedraw handlers 以按照您想要的方式设置域。

这是一个函数

  • 获取图表列表
  • 创建一个 preRender/preRedraw 处理程序
    • 通过连接所有图表的 .group().all() 并应用 d3.max()
    • 计算所有图表中所有值的最大值
    • 并将域 [0, maxY] 应用到图表
    • 调用 .rescale() 告诉图表比例已经改变:

处理人:

const common_elasticY = charts => chart => {
    const maxY = d3.max(Array.prototype.concat.apply([],
        charts.map(c => c.group().all())), kv => kv.value);
    chart.y().domain([0, maxY]);
    chart.rescale();
};

在图表列表中实例化处理程序:

const preHandler = common_elasticY([yearBarChart, spendBarChart]);

为每个图表安装 preRenderpreRedraw 事件的处理程序:

yearBarChart.on('preRender', preHandler)
  .on('preRedraw', preHandler);
spendBarChart.on('preRender', preHandler)
  .on('preRedraw', preHandler);

Demo fiddle.