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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:10:15