Chrome中应用linearGradient的SVG Path特定数值组合无法显示
问题原因
这是Chromium内核(Chrome、Edge、国内套壳Chromium的浏览器均受影响)SVG渲染模块的已知边界bug,Firefox、Safari使用独立渲染引擎不会触发该问题,具体触发逻辑如下:
- 你用D3生成的三次贝塞尔路径本身接近绝对水平:起点、两个控制点、终点的Y坐标差值最大仅为0.0000023左右,在Chrome的浮点精度边界计算逻辑下,该路径的垂直方向边界框(bbox)高度会被错误判定为0。
- 当描边使用纯色时,渲染流程不需要依赖路径bbox做坐标映射,哪怕bbox计算异常也能正常绘制描边,因此表现正常。
- 当描边使用默认配置的
linearGradient时,渐变默认采用gradientUnits="objectBoundingBox"模式,需要基于路径的bbox来计算渐变的起止映射坐标。一旦bbox的任意维度被判定为0,渲染引擎会直接判定该路径的渐变描边为无效绘制对象,跳过渲染,导致图形不显示。 - 你对任意坐标做极小微调时,刚好打破了浮点计算的临界值,让bbox计算出的高度不再为0,渐变映射逻辑恢复正常,图形就可以正常显示,和你修改哪个位置的数值没有直接关系。
解决方案
因为D3自动生成的路径数值无法手动干预,可直接采用以下任意一种方案绕开bug,均不会产生可感知的视觉差异:
- 修改渐变配置,改用
userSpaceOnUse作为渐变坐标单位,从根源绕开对路径bbox计算的依赖:
其中x1、x2对应路径在画布上的实际左右X坐标(你的路径外层加了<linearGradient id="gradient0" x1="46" y1="15.5" x2="854" y2="15.5" gradientUnits="userSpaceOnUse" > <stop offset="0%" stop-color="#05a" /> <stop offset="100%" stop-color="#0af" /> </linearGradient>translate(10,10),起点X36+10=46,终点X844+10=854),y值填路径Y坐标+10的近似值即可,水平渐变下Y值的微小偏差不会影响渲染效果。 - 在D3生成路径元素后,给路径的
transform属性增加一个极小的垂直偏移,比如追加translate(0, 1e-6),不需要修改路径d属性即可打破bbox计算的临界值。 - 如果不方便修改SVG元素属性,也可以在D3输出路径d字符串后,给所有Y坐标统一加1e-6量级的固定偏移,偏移量远小于人眼可识别的像素差,不会影响图表展示效果。
内容的提问来源于stack exchange,提问作者Iwan Satria
相关产品推荐
相关产品推荐

