如何制作发散且垂直居中的D3堆叠条形图?
D3.js堆叠条形图垂直居中middle组的实现阶段选择
结论:两种阶段都能实现,更推荐在绘图阶段调整,适配艺术创作的灵活需求。
数据预处理阶段实现
- 核心思路:直接修改原始数据结构,把
middle组的数值拆分为正负两部分,让堆叠后自然跨中线。
比如遍历CSV数据时,给每条数据新增两个字段:
之后堆叠时用data.forEach(d => { d.middle_top = +d.middle / 2; d.middle_bottom = -d.middle / 2; });middle_top和middle_bottom替换原有的middle字段,同时让另外两组(比如left设为负、right设为正)分别分布在中线两侧。 - 缺点:数据被修改,后续如果要调整middle组的上下比例(比如不是严格对半),需要重新处理数据,灵活性不足。
绘图阶段实现(推荐)
- 核心思路:保留原始数据,通过调整比例尺、堆叠偏移量来实现居中效果,更适合艺术可视化的灵活调整。
- 具体操作步骤:
- 用
d3.stack()正常计算所有组的堆叠数据,得到各层的[y0, y1]范围。 - 提取
middle组的总高度:遍历堆叠结果找到对应层,计算middleHeight = d3.max(stackedData, d => d[0].data.middle)(或根据堆叠结果直接计算总高度)。 - 调整y轴比例尺的定义域,让中线(y=0)对应middle组的中点:
const offset = middleHeight / 2; const yScale = d3.scaleLinear() .domain([-offset, totalChartHeight - offset]) // totalChartHeight为所有组的总堆叠高度 .range([height, 0]); - 绘制矩形时,直接使用调整后的比例尺计算y坐标,或者在原始堆叠y值基础上减去偏移量:
svg.selectAll("rect") .data(stackedData) .enter() .append("rect") .attr("x", d => xScale(d.data.category)) .attr("y", d => yScale(d[0] - offset)) .attr("height", d => yScale(d[1] - offset) - yScale(d[0] - offset)) .attr("width", xScale.bandwidth());
- 用
- 优点:原始数据完全保留,随时可以修改middle组的上下比例(比如改成1/3在上、2/3在下),只需要调整
offset的计算逻辑,适配艺术创作的多样需求。
总结
如果不需要后续调整比例,数据预处理的方式更直接;但艺术用途的可视化通常需要频繁调整视觉效果,绘图阶段调整的灵活性更高,是更优选择。
内容的提问来源于stack exchange,提问作者atowe
相关产品推荐
相关产品推荐

