You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在不修改宽高的情况下为D3 Circos/和弦图设置全局内边距?

给D3和弦图添加全局内边距(不修改宽高)

我明白你想要给和弦图四周加内边距,但又不想改动原本的svg宽高——直接设置样式没生效的问题很常见,因为svg的padding属性行为和普通HTML元素不一样,而且和弦图的布局是基于初始宽高计算的,得换个方式处理。

这里有个可靠的解决方案,核心思路是用一个容器<g>元素把整个和弦图内容"挪"到svg内部,同时调整布局的可用尺寸来适配内边距:

具体步骤

  • 定义内边距值:先设置你想要的上下左右内边距,比如{ top: 30, right: 30, bottom: 30, left: 30 }
  • 添加容器g元素:在svg内部创建一个<g>,用translate属性把它平移到内边距的起始位置(左内边距和上内边距的数值)
  • 调整布局尺寸:把和弦图的布局计算基于「原svg宽高减去对应内边距」后的可用空间
  • 将所有图表元素挂载到容器g:确保弧、和弦这些元素都添加到这个容器里,而不是直接加在svg上

完整示例代码

// 保持原有的svg宽高,不做修改
const width = 600;
const height = 600;

// 自定义全局内边距,按需调整数值
const padding = { top: 30, right: 30, bottom: 30, left: 30 };

// 创建svg,宽高保持原始设置
const svg = d3.select("#my_dataviz")
  .append("svg")
    .attr("width", width)
    .attr("height", height);

// 创建容器g,平移到内边距的起始位置
const chartContainer = svg.append("g")
  .attr("transform", `translate(${padding.left}, ${padding.top})`);

// 计算布局可用的宽高:原尺寸减去对应方向的内边距
const usableWidth = width - padding.left - padding.right;
const usableHeight = height - padding.top - padding.bottom;

// 初始化和弦布局,使用调整后的可用尺寸
const chord = d3.chord()
  .padAngle(0.05)
  .sortSubgroups(d3.descending);

// 调整弧的半径,基于可用宽度计算
const arc = d3.arc()
  .innerRadius(usableWidth / 2 - 100)
  .outerRadius(usableWidth / 2 - 50);

// 调整和弦的半径,同样基于可用宽度
const ribbon = d3.ribbon()
  .radius(usableWidth / 2 - 100);

// 加载并处理数据(这里用示例数据)
d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/chord.json").then(function(data) {
  const matrix = data.matrix;
  const names = data.names;
  const res = chord(matrix);

  // 绘制外部弧,挂载到容器g上
  chartContainer.selectAll(".arc-group")
    .data(res.groups)
    .enter()
    .append("g")
    .attr("class", "arc-group")
    .append("path")
      .style("fill", "#69b3a2")
      .style("stroke", "#000")
      .attr("d", arc);

  // 绘制内部和弦,同样挂载到容器g上
  chartContainer.selectAll(".ribbon")
    .data(res)
    .enter()
    .append("path")
    .attr("class", "ribbon")
      .attr("d", ribbon)
      .style("fill", d => d3.schemeSet3[d.source.index])
      .style("stroke", "#000");
});

为什么这个方法生效?

  • 我们没有修改svg本身的宽高,只是通过translate把整个图表内容向内偏移,留出了指定的内边距
  • 同时调整了和弦布局的可用尺寸,确保图表内容会适配svg内部的可用空间,不会超出内边距范围
  • 相比直接给svg加padding样式,这种方式在所有浏览器里的表现都更稳定,因为svg的padding属性并不像HTML元素那样被广泛支持和规范

内容的提问来源于stack exchange,提问作者shrikant chintakindi

火山引擎 最新活动