D3.js环形图:为点击高亮扇区添加投影阴影效果
解决D3.js环形图点击高亮的投影阴影问题
嘿,我明白你想要给点击后的环形扇区加上自然的投影阴影——用stroke确实达不到那种柔和的真实阴影效果,毕竟stroke是沿着路径描边,而我们需要的是整个扇区的扩散式投影。这里有个更靠谱的方案,用SVG的filter来实现真正的drop shadow效果。
核心思路
SVG的<feDropShadow>滤镜可以给图形添加符合视觉预期的投影,我们只需要先在SVG中定义好这个滤镜,然后在点击扇区时,给选中的元素应用该滤镜,同时取消之前选中元素的滤镜即可。
修改后的完整代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title> D3 Js Example </title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" media="screen" href="main.css" /> </head> <body> <div id="my_dataviz"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.7/d3.min.js" ></script> <script> var lastSelected = ""; var firstSelected = ""; var width = 450 height = 450 margin = 40 var radius = Math.min(width, height) / 2 - margin var normalArc = d3.arc().outerRadius(radius - 30).innerRadius(radius - 70); var biggerArc = d3.arc().outerRadius(radius - 80).innerRadius(radius - 10); var svg = d3.select("#my_dataviz") .append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); // 定义投影阴影滤镜 svg.append("defs") .append("filter") .attr("id", "drop-shadow") .append("feDropShadow") .attr("dx", 0) // 阴影水平偏移量 .attr("dy", 3) // 阴影垂直偏移量 .attr("stdDeviation", 5) // 阴影模糊程度 .attr("flood-opacity", 0.5) // 阴影透明度 .attr("flood-color", "#000"); // 阴影颜色 var data = {a: 9, b: 20, c:30, d:8, e:12} var color = d3.scaleOrdinal() .domain(data) .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56"]) var pie = d3.pie() .value(function(d) {return d.value; }) var data_ready = pie(d3.entries(data)) svg .selectAll('path') .data(data_ready) .enter() .append('path') .attr('d', function(d, index) { // 如果是第一个扇区,默认放大显示 if (index === 0) { firstSelected = this; return biggerArc(d); } else { return normalArc(d); } }) .attr('fill', function(d){ return(color(d.data.key)) }) .style("opacity", 0.7) .on("click", function(d) { // 重置第一个选中的扇区(如果存在) if (firstSelected) { d3.select(firstSelected) .attr("d", normalArc) .style("filter", "none"); firstSelected = false; } // 重置上一个选中的扇区 if (lastSelected) { d3.select(lastSelected) .attr("d", normalArc) .style("filter", "none"); } // 高亮当前选中的扇区:放大+应用投影滤镜 d3.select(this) .attr("d", biggerArc) .style("filter", "url(#drop-shadow)"); lastSelected = this; }) </script> </body> </html>
关键修改点说明
- 添加SVG滤镜:在SVG的
defs中定义了id为drop-shadow的滤镜,通过feDropShadow参数可以灵活调整阴影的偏移、模糊度、透明度和颜色——比如增大stdDeviation会让阴影更柔和,调整dy可以改变阴影的垂直位置。 - 替换stroke为滤镜:点击事件里不再用stroke模拟阴影,而是给选中的扇区应用
filter: url(#drop-shadow),取消选中时设置为none,这样阴影会跟随整个扇区的形状,视觉效果更自然。 - 保留原有放大逻辑:叠加投影效果的同时,保留了你原本的扇区放大交互,让高亮的层次感更明显。
这样修改后,点击扇区时不仅会放大,还会出现柔和的扩散式投影,完全符合你想要增强高亮表现的需求~
内容的提问来源于stack exchange,提问作者yasarui
相关产品推荐
相关产品推荐

