如何在SVG遮罩内部添加投影效果?
解决SVG遮罩内侧添加投影的问题
核心结论:无法直接在遮罩(mask)内部实现内侧投影,因为遮罩仅控制元素的可见范围,不参与视觉效果的渲染。但可以通过滤镜组合或分层绘制的方式实现需求,无需手动转换为路径。
方法一:使用SVG滤镜实现内侧投影
通过<filter>组合<feDropShadow>和<feComposite>,先生成朝向内侧的投影,再与原遮罩后的边框叠加:
<svg xmlns="http://www.w3.org/2000/svg" width="640" height="640"> <defs> <!-- 原遮罩 --> <mask id="bezelMask"> <rect width="100%" height="100%" fill="white" /> <circle cx="50%" cy="50%" r="43.75%" fill="black" /> <rect width="100%" height="6.25%" y="65%" fill="white" /> <rect width="100%" height="35%" y="71.25%" fill="black" /> </mask> <!-- 内侧投影滤镜 --> <filter id="innerShadow"> <!-- 生成投影,调整dx/dy控制方向,stdDeviation控制模糊度 --> <feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="rgba(0,0,0,0.5)" /> <!-- 只保留投影中位于原形状内侧的部分 --> <feComposite operator="in" in2="SourceGraphic" /> <!-- 将投影与原图形叠加 --> <feMerge> <feMergeNode /> <feMergeNode in="SourceGraphic" /> </feMerge> </filter> </defs> <g id="circular-face"> <!-- 应用滤镜和遮罩,注意顺序:先滤镜后遮罩 --> <circle id="bezel" r="50%" cx="50%" cy="50%" fill="red" filter="url(#innerShadow)" mask="url(#bezelMask)" /> </g> </svg>
原理说明:
<feDropShadow>生成向外的投影,但通过<feComposite operator="in">,只保留投影与原图形重叠的部分(即内侧区域)。<feMerge>将投影和原边框叠加,实现内侧阴影效果。
方法二:分层绘制边框与投影
直接绘制边框的实际形状(无需遮罩),然后给形状添加内侧投影,这种方式更直观:
<svg xmlns="http://www.w3.org/2000/svg" width="640" height="640"> <defs> <!-- 定义边框的形状为clipPath,方便复用 --> <clipPath id="bezelShape"> <rect width="100%" height="100%" /> <circle cx="50%" cy="50%" r="43.75%" /> <rect width="100%" height="35%" y="71.25%" /> </clipPath> <!-- 内侧投影滤镜 --> <filter id="innerShadowAlt"> <feDropShadow dx="0" dy="3" stdDeviation="5" flood-color="rgba(0,0,0,0.6)" /> <feComposite operator="in" in2="SourceGraphic" /> <feMerge> <feMergeNode /> <feMergeNode in="SourceGraphic" /> </feMerge> </filter> </defs> <g id="circular-face"> <!-- 绘制边框:用大圆形裁剪后得到目标形状 --> <g clip-path="url(#bezelShape)"> <circle r="50%" cx="50%" cy="50%" fill="red" filter="url(#innerShadowAlt)" /> </g> <!-- 绘制底部横条(对应原遮罩中y=65%的矩形) --> <rect width="100%" height="6.25%" y="65%" fill="red" filter="url(#innerShadowAlt)" /> </g> </svg>
原理说明:
- 用
<clipPath>定义边框的可见区域,替代原遮罩的逻辑。 - 分别绘制圆形边框和底部横条,都应用内侧投影滤镜,实现完整的悬浮效果。
关键注意事项
- 滤镜的顺序很重要:先应用滤镜,再应用遮罩/裁剪,否则滤镜会被遮罩截断,无法生效。
- 调整
<feDropShadow>的dx/dy和stdDeviation参数,可以控制阴影的方向和模糊程度,适配不同的设计需求。
内容的提问来源于stack exchange,提问作者Grayda
相关产品推荐
相关产品推荐

