SVG多渐变填充三角形边缘渲染异常,如何解决?
SVG多层渐变填充三角形边缘渲染异常的解决办法
你用SVG制作颜色选择器的饱和度-亮度三角形时,叠加多个径向渐变填充的多边形后,所有浏览器都出现边缘渲染异常的问题。你的代码如下:
body{ background: black; }
<svg xmlns="http://www.w3.org/2000/svg" width="88" height="88" class="saturation-brightness"><defs> <radialGradient id="darks" cx="7.63px" cy="65px" r="72.7446px" gradientUnits="userSpaceOnUse"> <stop offset="0%" stop-color="#000000" /> <stop offset="100%" stop-color="rgba(0, 0, 0, 0)" /> </radialGradient> <radialGradient id="lights" cx="80.37" cy="65px" r="72.7446px" gradientUnits="userSpaceOnUse"> <stop offset="0%" stop-color="#FFFFFF" /> <stop offset="100%" stop-color="rgba(255, 255, 255, 0)" /> </radialGradient> <radialGradient id="mids" cx="44px" cy="65px" r="36.37px" gradientUnits="userSpaceOnUse"> <stop offset="0%" stop-color="#808080" /> <stop offset="100%" stop-color="rgba(128, 128, 128, 0)" /> </radialGradient> </defs> <polygon points="44,2 7.63,65 80.37,65" fill="red" /> <polygon points="44,2 7.63,65 80.37,65" fill="url(#mids)" /> <polygon points="44,2 7.63,65 80.37,65" fill="url(#darks)" /> <polygon points="44,2 7.63,65 80.37,65" fill="url(#lights)" /> </svg>
下面是几个实用的解决方法:
方法1:用SVG滤镜合并所有效果到单个多边形
多层多边形叠加时,浏览器的抗锯齿和渲染精度容易导致边缘出现缝隙或重影。用滤镜把所有颜色渐变效果合并到单个多边形上,就能彻底避免这个问题:
<svg xmlns="http://www.w3.org/2000/svg" width="88" height="88" class="saturation-brightness"> <defs> <filter id="colorTriangleFilter"> <!-- 基础红色层 --> <feFlood flood-color="red" result="base"/> <!-- 中间灰色径向渐变层 --> <feRadialGradient id="midsGrad" cx="44px" cy="65px" r="36.37px" gradientUnits="userSpaceOnUse"> <stop offset="0%" stop-color="#808080" /> <stop offset="100%" stop-color="rgba(128, 128, 128, 0)" /> </feRadialGradient> <feFlood flood-color="url(#midsGrad)" result="mids"/> <feComposite in="base" in2="mids" operator="over" result="baseMids"/> <!-- 暗部径向渐变层 --> <feRadialGradient id="darksGrad" cx="7.63px" cy="65px" r="72.7446px" gradientUnits="userSpaceOnUse"> <stop offset="0%" stop-color="#000000" /> <stop offset="100%" stop-color="rgba(0, 0, 0, 0)" /> </feRadialGradient> <feFlood flood-color="url(#darksGrad)" result="darks"/> <feComposite in="baseMids" in2="darks" operator="over" result="baseMidsDarks"/> <!-- 亮部径向渐变层 --> <feRadialGradient id="lightsGrad" cx="80.37" cy="65px" r="72.7446px" gradientUnits="userSpaceOnUse"> <stop offset="0%" stop-color="#FFFFFF" /> <stop offset="100%" stop-color="rgba(255, 255, 255, 0)" /> </feRadialGradient> <feFlood flood-color="url(#lightsGrad)" result="lights"/> <feComposite in="baseMidsDarks" in2="lights" operator="over" result="final"/> </filter> </defs> <polygon points="44,2 7.63,65 80.37,65" filter="url(#colorTriangleFilter)" /> </svg>
这个方法通过滤镜在单个多边形上依次叠加所有颜色效果,没有多个形状的边缘对齐问题,渲染更稳定。
方法2:给上层多边形添加同色细描边
给每个叠加的多边形添加和底层颜色一致的细微描边,填充边缘的缝隙:
<svg xmlns="http://www.w3.org/2000/svg" width="88" height="88" class="saturation-brightness"><defs> <radialGradient id="darks" cx="7.63px" cy="65px" r="72.7446px" gradientUnits="userSpaceOnUse"> <stop offset="0%" stop-color="#000000" /> <stop offset="100%" stop-color="rgba(0, 0, 0, 0)" /> </radialGradient> <radialGradient id="lights" cx="80.37" cy="65px" r="72.7446px" gradientUnits="userSpaceOnUse"> <stop offset="0%" stop-color="#FFFFFF" /> <stop offset="100%" stop-color="rgba(255, 255, 255, 0)" /> </radialGradient> <radialGradient id="mids" cx="44px" cy="65px" r="36.37px" gradientUnits="userSpaceOnUse"> <stop offset="0%" stop-color="#808080" /> <stop offset="100%" stop-color="rgba(128, 128, 128, 0)" /> </radialGradient> </defs> <polygon points="44,2 7.63,65 80.37,65" fill="red" /> <polygon points="44,2 7.63,65 80.37,65" fill="url(#mids)" stroke="red" stroke-width="0.5" /> <polygon points="44,2 7.63,65 80.37,65" fill="url(#darks)" stroke="red" stroke-width="0.5" /> <polygon points="44,2 7.63,65 80.37,65" fill="url(#lights)" stroke="red" stroke-width="0.5" /> </svg>
可以根据实际渲染情况微调stroke-width的数值,比如0.3~0.8px之间,既能填补缝隙又不会影响渐变效果。
方法3:微调上层多边形坐标
把上层多边形的坐标稍微放大一点,让它完全覆盖底层多边形的边缘,比如:
<polygon points="44,2 7.63,65 80.37,65" fill="red" /> <!-- 上层多边形坐标向外偏移0.5px --> <polygon points="43.5,1.5 7.13,65.5 80.87,65.5" fill="url(#mids)" /> <polygon points="43.5,1.5 7.13,65.5 80.87,65.5" fill="url(#darks)" /> <polygon points="43.5,1.5 7.13,65.5 80.87,65.5" fill="url(#lights)" />
这种方式通过扩大上层形状的范围,掩盖边缘的渲染误差,适合快速调整。
内容的提问来源于stack exchange,提问作者Ood
相关产品推荐
相关产品推荐

