如何用嵌套SVG作为SVG中feTile的输入实现自包含图案阴影?
内嵌SVG纹理实现带图案的阴影(跨浏览器兼容方案)
你想在SVG中用feTile+feOffset实现带自定义图案的阴影,同时保持文件自包含,无需base64编码或外部引用。直接用<feImage xlink:href="#pattern-id">引用内部元素的方式在多浏览器中不兼容,且复用滤镜时会失效,以下是可行的解决方案:
问题根源
- 部分浏览器(如Firefox)未实现
<feImage>对内部SVG/<g>元素的引用支持,仅支持外部资源或data URI; - 直接用
<g>作为纹理源时,因无明确尺寸定义,滤镜无法正确计算重复范围,导致多元素复用滤镜异常。
跨浏览器实现代码
<?xml version="1.0" encoding="UTF-8"?> <svg version="1.1" width="100%" height="1000" xmlns="http://www.w3.org/2000/svg"> <defs> <!-- 1. 用原生<pattern>定义可复用的纹理图案 --> <pattern id="dotted-pattern" patternUnits="userSpaceOnUse" width="4" height="4"> <rect width="4" height="4" fill="#fff"/> <circle cx="1" cy="1" r="1" fill="#000"/> </pattern> <!-- 2. 定义带纹理阴影的滤镜 --> <filter id="pattern-shadow" height="130%" x="-15%" y="-15%" width="130%"> <!-- 生成原图形的遮罩,限制纹理仅在原图形范围内 --> <feFlood result="empty-fill"/> <feComposite in="empty-fill" in2="SourceGraphic" operator="in" result="shape-mask"/> <!-- 将遮罩重复填充为纹理基底 --> <feTile in="shape-mask" result="mask-tile"/> <!-- 给基底应用定义好的纹理图案 --> <feFlood flood-color="transparent" result="pattern-base"/> <feComposite in="pattern-base" in2="mask-tile" operator="over" result="textured-shadow" style="fill: url(#dotted-pattern)"/> <!-- 偏移纹理阴影 --> <feOffset dx="30" dy="20" result="offset-shadow"/> <!-- 合并阴影与原图形 --> <feMerge> <feMergeNode in="offset-shadow"/> <feMergeNode in="SourceGraphic"/> </feMerge> </filter> </defs> <!-- 应用滤镜的元素 --> <rect fill="#ffffff" stroke="#000000" x="10" y="10" width="200" height="100" style="filter:url(#pattern-shadow)" /> <!-- 复用滤镜到第二个元素 --> <rect fill="#ffffff" stroke="#000000" x="220" y="10" width="200" height="100" style="filter:url(#pattern-shadow)" /> </svg>
方案优势
- 完全自包含:无需base64编码或外部资源引用;
- 跨浏览器兼容:支持Chrome、Firefox、Safari等主流浏览器;
- 可复用性:同一滤镜可应用到多个元素,不会出现渲染异常;
- 灵活调整:修改
<pattern>内的图形即可快速调整纹理样式。
内容的提问来源于stack exchange,提问作者pinpox
相关产品推荐
相关产品推荐

