使用stroke-dasharray的SVG饼图:扇区box-shadow无法生效求助
如何为stroke-dasharray实现的SVG饼图扇区添加不改变尺寸的阴影效果?
我通过stroke-dasharray实现了SVG饼图,现在需要给特定扇区添加阴影来标记激活状态,但遇到了问题:
- 直接用CSS的
filter: drop-shadow(0 4px 25px rgba(0, 0, 0, 0.75))没有效果 - 尝试在SVG内部集成
<filter>,却导致扇区整体尺寸被改变
预期效果如下:
示例代码
CSS代码
body { padding: 1rem; background: #bbb; text-align: center; } svg:not(:root) { overflow: visible; } svg { height: 280px; width: 280px; border: 20px solid white; border-radius: 50%; [id="1"] { filter: drop-shadow(0 4px 25px rgba(0, 0, 0, 0.75)); } }
HTML代码
<!-- 4 Elements --> <svg height="20" width="20" viewBox="0 0 20 20"> <circle id="1" r="5" cx="10" cy="10" stroke="tomato" stroke-width="10" stroke-dasharray="calc(90 * 31.42 / 360) 31.42" transform="rotate(-90)" transform-origin="center center" /> <circle r="5" cx="10" cy="10" fill="transparent" stroke="blue" stroke-width="10" stroke-dasharray="calc(90 * 31.42 / 360) 31.42" transform-origin="center center" /> <circle r="5" cx="10" cy="10" fill="transparent" stroke="yellow" stroke-width="10" stroke-dasharray="calc(90 * 31.42 / 360) 31.42" transform="rotate(90) scale(1.15)" transform-origin="center center" /> <circle r="5" cx="10" cy="10" fill="transparent" stroke="green" stroke-width="10" stroke-dasharray="calc(90 * 31.42 / 360) 31.42" transform="rotate(180)" transform-origin="center center" /> </svg>
解决方法
方法一:自定义SVG Filter并调整边界
SVG默认的filter会将元素边界作为阴影的范围,导致元素被挤压。我们可以通过调整filter的x、y、width、height参数,给阴影留出足够空间,同时不影响原扇区尺寸。
修改后的SVG代码:
<svg height="20" width="20" viewBox="0 0 20 20"> <!-- 定义阴影滤镜 --> <defs> <filter id="sectorShadow" x="-20%" y="-20%" width="140%" height="140%"> <feDropShadow dx="0" dy="4" stdDeviation="12" flood-color="rgba(0,0,0,0.75)"/> </filter> </defs> <circle id="1" r="5" cx="10" cy="10" stroke="tomato" stroke-width="10" stroke-dasharray="calc(90 * 31.42 / 360) 31.42" transform="rotate(-90)" transform-origin="center center" filter="url(#sectorShadow)" /> <!-- 其他扇区代码不变 --> <circle r="5" cx="10" cy="10" fill="transparent" stroke="blue" stroke-width="10" stroke-dasharray="calc(90 * 31.42 / 360) 31.42" transform-origin="center center" /> <circle r="5" cx="10" cy="10" fill="transparent" stroke="yellow" stroke-width="10" stroke-dasharray="calc(90 * 31.42 / 360) 31.42" transform="rotate(90) scale(1.15)" transform-origin="center center" /> <circle r="5" cx="10" cy="10" fill="transparent" stroke="green" stroke-width="10" stroke-dasharray="calc(90 * 31.42 / 360) 31.42" transform="rotate(180)" transform-origin="center center" /> </svg>
说明:
x="-20%"和y="-20%"让滤镜范围向上下左右扩展20%width="140%"和height="140%"保证滤镜覆盖足够区域,阴影不会被截断stdDeviation控制阴影模糊程度,可根据需求调整
方法二:双重元素模拟阴影
复制目标扇区元素,将底层元素仅用于显示阴影,上层放置原扇区。这种方法兼容性更好,不会受SVG filter边界的影响。
修改后的目标扇区代码:
<svg height="20" width="20" viewBox="0 0 20 20"> <!-- 底层阴影元素 --> <circle r="5" cx="10" cy="10" stroke="tomato" stroke-width="10" stroke-dasharray="calc(90 * 31.42 / 360) 31.42" transform="rotate(-90)" transform-origin="center center" filter="drop-shadow(0 4px 25px rgba(0, 0, 0, 0.75))" /> <!-- 上层原扇区元素 --> <circle id="1" r="5" cx="10" cy="10" stroke="tomato" stroke-width="10" stroke-dasharray="calc(90 * 31.42 / 360) 31.42" transform="rotate(-90)" transform-origin="center center" /> <!-- 其他扇区代码不变 --> </svg>
说明:
- 底层元素的阴影会被上层元素覆盖中间部分,只露出边缘阴影,符合预期效果
- 如果需要调整阴影颜色或透明度,直接修改底层元素的filter参数即可
内容的提问来源于stack exchange,提问作者Mizu
相关产品推荐
相关产品推荐

