SVG内阴影仅显示为轮廓,如何实现预期的立体内阴影效果?
提问内容
我尝试为SVG添加内阴影,期望实现如下效果:
但目前实际实现的效果不符合需求,如下所示:
我参照Stack Overflow的现有回答,为所有path添加了filter="url(#inset-shadow)"属性,使用的滤镜代码如下:
<filter id="inset-shadow"> <feComponentTransfer in="SourceAlpha" result="inset-selection"> <feFuncA type="discrete" tableValues="0 1 1 1 1 1" /> </feComponentTransfer> <feComponentTransfer in="SourceGraphic" result="original-no-fill"> <feFuncA type="discrete" tableValues="0 0 1" /> </feComponentTransfer> <feColorMatrix type="matrix" in="original-no-fill" result="new-source-alpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" /> <feGaussianBlur in="new-source-alpha" result="blur" stdDeviation="5" /> <feGaussianBlur in="new-source-alpha" result="blur2" stdDeviation="10" /> <feGaussianBlur in="new-source-alpha" result="blur3" stdDeviation="15" /> <feMerge result="blur"> <feMergeNode in="blur" mode="normal" /> <feMergeNode in="blur2" mode="normal" /> <feMergeNode in="blur3" mode="normal" /> </feMerge> <feComposite operator="in" in="inset-selection" in2="blur" result="inset-blur" /> <feComposite operator="over" in="original-no-fill" in2="inset-blur" /> </filter>
但实际运行后仅为每个路径添加了类似描边的效果,未生成正确内阴影,请问如何调整才能为SVG图形添加正确的内阴影,达到顶部示例的立体效果?
解答
你的滤镜没有生成正确内阴影的核心原因有两点:
- 没有设置阴影偏移量,模糊后的效果和原路径完全对齐,只会在边缘显示类似描边的效果,没有向内凹陷的立体感
- 透明度转换的逻辑错误,把原图形填充区域的透明度处理异常,导致阴影裁切范围不对
你可以直接替换为下面的滤镜代码,默认模拟左上方向的光源,和你示例的立体效果匹配:
<filter id="inset-shadow" x="-20%" y="-20%" width="140%" height="140%"> <!-- 提取原图形的Alpha通道 --> <feComponentTransfer in="SourceAlpha"> <feFuncA type="table" tableValues="0 1" /> </feComponentTransfer> <!-- 生成阴影的基础形态:偏移+模糊+调暗 --> <feOffset dx="2" dy="2" result="offset-blur" /> <feGaussianBlur stdDeviation="3" result="blur" /> <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.7 0" result="shadow" /> <!-- 裁切出路径内部的阴影区域 --> <feComposite operator="out" in="shadow" in2="SourceAlpha" result="shadow-outside" /> <feComposite operator="arithmetic" in="shadow-outside" in2="SourceAlpha" k1="0" k2="-1" k3="1" k4="0" result="inset-shadow" /> <!-- 把原图形和内阴影合并 --> <feComposite operator="over" in="inset-shadow" in2="SourceGraphic" /> </filter>
使用方式和你之前的逻辑一致,直接给需要加内阴影的path添加filter="url(#inset-shadow)"属性即可。如果需要调整阴影效果,可以修改这几个参数:
dx/dy:调整阴影的偏移方向和距离,对应光源的方向stdDeviation:调整阴影的模糊程度,数值越大阴影越柔和- feColorMatrix里的最后一行第四个值:调整阴影的不透明度,数值越大阴影越深
内容的提问来源于stack exchange,提问作者Sam Germain
相关产品推荐
相关产品推荐

