基于D3.js的半饼图添加进度箭头及颜色控制功能需求
D3.js半饼图添加进度箭头及实时更新实现方案
下面是满足你需求的完整实现代码,包含进度跟随箭头、颜色配置、实时更新以及中心裁剪圆的颜色控制功能:
<html> <head> <title>D3.js 半饼图带进度箭头</title> <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script> <style> .arrow-path { stroke-linecap: round; stroke-linejoin: round; } </style> </head> <body> <button onclick="updateProgress(75)">更新到75%</button> <button onclick="updateProgress(30)">更新到30%</button> <script> // 可配置参数 const config = { width: 120, height: 120, outerRadius: 60, innerRadius: 50, centerCircleRadius: 45, centerCircleColor: '#ffffff', // 中心裁剪圆颜色 arrowColor: '#ff0000', // 箭头颜色 pieColors: ['#046395', '#d62828'] // 饼图分段颜色 }; // 初始化数据 let currentProgress = 60; const data = [ {"label": "Completed", "value": currentProgress}, {"label": "Remaining", "value": 100 - currentProgress} ]; // 清除已有SVG d3.select("body").selectAll('svg').remove(); // 创建SVG容器 const svg = d3.select("body") .append('svg') .attr('width', config.width) .attr('height', config.height) .append('g') .attr('class', 'piechart') .attr('transform', `translate(${config.width / 2}, ${config.height / 2})`); // 绘制中心裁剪圆 svg.append('circle') .attr('r', config.centerCircleRadius) .attr('fill', config.centerCircleColor); // 创建饼图生成器 const pie = d3.pie() .startAngle(-90 * (Math.PI / 180)) .endAngle(90 * (Math.PI / 180)) .padAngle(.02) .sort(null) .value(d => d.value); // 创建弧生成器 const arc = d3.arc() .outerRadius(config.outerRadius) .innerRadius(config.innerRadius); // 绘制饼图分段 const segments = svg.append('g').attr('class', 'segments'); let slices = segments.selectAll('.arc') .data(pie(data)) .enter() .append('g') .attr('class', 'arc'); slices.append('path') .attr('d', arc) .attr('fill', (d, i) => config.pieColors[i]) .transition() .attrTween('d', function(d) { const i = d3.interpolate(d.startAngle + 0.1, d.endAngle); return t => { d.endAngle = i(t); return arc(d); } }); // 绘制进度箭头 const arrowGroup = svg.append('g').attr('class', 'arrow-group'); const arrowLength = config.centerCircleRadius - 5; arrowGroup.append('path') .attr('class', 'arrow-path') .attr('d', `M0,0 L${arrowLength},0 L${arrowLength - 8},-5 L${arrowLength},0 L${arrowLength - 8},5`) .attr('stroke', config.arrowColor) .attr('stroke-width', 2) .attr('fill', 'none'); // 初始化箭头位置 updateArrowPosition(currentProgress); // 实时更新函数 function updateProgress(newProgress) { currentProgress = Math.max(0, Math.min(100, newProgress)); // 更新数据 data[0].value = currentProgress; data[1].value = 100 - currentProgress; // 更新饼图 slices = segments.selectAll('.arc').data(pie(data)); // 处理更新过渡 slices.select('path') .transition() .duration(750) .attrTween('d', function(d) { const currentArc = d3.select(this).attr('d'); const oldAngle = arc.invert(currentArc).endAngle; const i = d3.interpolate(oldAngle, d.endAngle); return t => { d.endAngle = i(t); return arc(d); } }); // 更新箭头位置 updateArrowPosition(currentProgress); } // 更新箭头角度 function updateArrowPosition(progress) { // 计算角度:从-90度到90度对应0-100% const angle = -90 + (progress / 100) * 180; arrowGroup.transition() .duration(750) .attr('transform', `rotate(${angle})`); } </script> </body> </html>
关键功能说明
- 集中配置管理:所有可自定义的参数(颜色、尺寸等)都放在
config对象中,修改调整更便捷 - 中心裁剪圆:通过
circle元素绘制,颜色由centerCircleColor控制,覆盖在饼图中心形成视觉裁剪效果 - 进度箭头:用SVG路径绘制箭头,通过旋转容器组实现跟随进度;箭头颜色由
arrowColor控制,旋转角度根据百分比线性计算(0%对应-90度,100%对应90度) - 实时更新机制:
updateProgress函数接收新百分比,同步更新饼图数据与箭头位置,全程带平滑过渡动画 - 流畅过渡效果:饼图分段和箭头都使用D3过渡动画,保证更新过程自然顺滑
内容的提问来源于stack exchange,提问作者The Old County
相关产品推荐
相关产品推荐

