You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

d3.js自定义样式区域饼图实现咨询:替代传统老旧饼图

D3.js 实现曲线分区饼图方案

你要的这种类《Land of colors》的可视化效果,核心是把传统饼图指向圆心的直线边替换为向内凹陷的贝塞尔曲线,无需严格遵循Moser圆的数学规则,实现难度很低,完整实现逻辑如下:

前置依赖

引入D3.js v7版本即可,无其他额外依赖。

步骤1:数据格式化

先把你提供的KV结构原始数据,转换为带弧度映射的结构化数据:

// 你的原始数据
const rawData = {a: 9, b: 20, c:30, d:8, e:12};
// 转换为数组并计算各分类对应的圆周弧度
const dataArr = Object.entries(rawData).map(([key, value]) => ({name: key, value}));
const totalValue = d3.sum(dataArr, d => d.value);
// 用d3自带的pie生成器计算各分类的起始/结束弧度,和普通饼图逻辑一致
const pieData = d3.pie()
  .value(d => d.value)
  .sort(null) // 保持原始数据顺序,不需要按数值排序可以去掉这行
(dataArr);

步骤2:自定义曲线路径生成

替换传统饼图的d3.arc()生成器,自己写路径逻辑,用二次贝塞尔曲线生成向内凹陷的分区边:

// 画布和半径配置
const width = 600, height = 600;
const outerRadius = Math.min(width, height) / 2 * 0.85;
const innerControlRatio = 0.3; // 曲线内凹比例,0=完全贴合圆心(和传统饼图一致),1=完全贴合圆周(没有内凹),可自行调整

// 自定义分区路径生成函数
function generateCurveArc(d) {
  // 计算外弧两个端点的坐标
  const [x1, y1] = [
    outerRadius * Math.cos(d.startAngle - Math.PI / 2),
    outerRadius * Math.sin(d.startAngle - Math.PI / 2)
  ];
  const [x2, y2] = [
    outerRadius * Math.cos(d.endAngle - Math.PI / 2),
    outerRadius * Math.sin(d.endAngle - Math.PI / 2)
  ];
  // 计算贝塞尔曲线的控制点(弧中点往圆心偏移对应比例)
  const midAngle = (d.startAngle + d.endAngle) / 2;
  const controlRadius = outerRadius * innerControlRatio;
  const [cx, cy] = [
    controlRadius * Math.cos(midAngle - Math.PI / 2),
    controlRadius * Math.sin(midAngle - Math.PI / 2)
  ];
  // 拼接SVG路径
  return `M ${x1} ${y1}
          A ${outerRadius} ${outerRadius} 0 ${d.endAngle - d.startAngle > Math.PI ? 1 : 0} 1 ${x2} ${y2}
          Q ${cx} ${cy} ${x1} ${y1}
          Z`;
}

步骤3:渲染到页面

// 创建SVG画布
const svg = d3.select('body').append('svg')
  .attr('width', width)
  .attr('height', height)
  .append('g')
  .attr('transform', `translate(${width / 2}, ${height / 2})`);

// 配色方案,可自行替换
const colorScale = d3.scaleOrdinal(d3.schemeSet3);

// 渲染分区
svg.selectAll('.curve-arc')
  .data(pieData)
  .enter()
  .append('path')
  .attr('class', 'curve-arc')
  .attr('d', generateCurveArc)
  .attr('fill', (d, i) => colorScale(i))
  .attr('stroke', '#fff')
  .attr('stroke-width', 2)
  .attr('opacity', 0.8); // 半透明叠加更接近参考效果的通透质感

效果调整技巧

  • 改innerControlRatio的数值就能调整曲线的凹陷程度,想要更夸张的效果可以调到0.1,想要更饱满的分区调到0.5即可
  • 如果需要加参考效果里的内部交叉连线,额外遍历所有弧的端点,按需求配对渲染直线即可,不需要计算复杂的交点
  • 标签、悬停高亮等交互逻辑和普通饼图完全一致,直接复用常规饼图的交互代码就行

你要的参考效果如下:
参考效果示意图

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 10:39:03