使用D3.js实现带渐隐渐变效果的环形图问题求助
实现带渐隐渐变效果的D3.js环形图
问题背景
需要创建一款环形图,要求外侧为纯色环,内侧呈现从纯色向中心渐隐的渐变效果。此前尝试drop-shadow滤镜无法实现需求,改用双层饼图方案后,使用全局径向渐变时,渐变效果会随扇形角度发生扭曲,无法达到统一的渐隐效果。
解决方案
为每个扇形单独创建中心对齐的径向渐变,确保每个扇形的渐变方向都是从环形外侧(靠近纯色环的位置)向内过渡到透明,避免渐变随扇形角度变形。同时使用单个SVG容器管理两层饼图,简化布局。
完整代码
HTML部分
<html> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.14.2/d3.min.js"></script> <body> </body> </html>
JavaScript部分
const colors = ['red','green','purple','blue','orange','teal'] const data = [10,12,33,112,22,4]; const pie = d3.pie().padAngle(0.03); const arcs = pie(data); const outerRadius = 100; const innerRadius = 96; // 创建单个SVG容器 const svg = d3.select('body') .append('svg') .attr('width', 600) .attr('height', 600) .append("g") .attr("transform", "translate(100,100)"); const svgDefs = svg.append('defs'); // 为每个颜色创建专属径向渐变 colors.forEach((color, index) => { const gradient = svgDefs.append('radialGradient') .attr('id', `gradient-${index}`) .attr('cx', '0%') // 对齐环形中心 .attr('cy', '0%') .attr('r', '100%'); // 渐变范围覆盖整个扇形 gradient.append('stop') .attr('stop-color', color) .attr('offset', `${(innerRadius/outerRadius)*100}%`) // 从内层环的位置开始纯色 .attr('stop-opacity', 1); gradient.append('stop') .attr('stop-color', color) .attr('offset', '100%') // 中心位置完全透明 .attr('stop-opacity', 0); }); // 绘制内层渐隐饼图 svg.selectAll('.inner-arc') .data(arcs) .enter() .append('path') .attr('class', 'inner-arc') .attr('d', d => d3.arc()({...d, innerRadius: 0, outerRadius: innerRadius})) .style('fill', (d, index) => `url(#gradient-${index})`); // 绘制外层纯色环 svg.selectAll('.outer-arc') .data(arcs) .enter() .append('path') .attr('class', 'outer-arc') .attr('d', d => d3.arc()({...d, innerRadius: innerRadius, outerRadius: outerRadius})) .style('fill', (d, index) => colors[index]);
代码解释
- 统一SVG容器:避免多层SVG的定位问题,所有元素都在同一个SVG中管理。
- 专属径向渐变:每个扇形对应一个渐变,
cx和cy设为0%(环形中心),确保渐变方向统一从外向内。 - 渐变节点设置:
- 第一个
stop在(innerRadius/outerRadius)*100%位置(即内层环的外侧),保持纯色不透明 - 第二个
stop在100%位置(环形中心),设置为完全透明
- 第一个
- 分层绘制:先绘制内层渐隐扇形,再绘制外层纯色环,保证层级正确。
内容的提问来源于stack exchange,提问作者Gal Ziv
相关产品推荐
相关产品推荐

