在Safari中对SVG组应用CSS transform导致文本元素闪烁的问题
Safari下SVG组变换时文本元素闪烁的解决办法
问题现象
在Safari中对SVG的<g>元素应用变换(如D3.js的缩放交互)时,组内的<text>元素会出现闪烁,而圆形等其他图形元素变换流畅;Firefox和Chrome则无此异常。
有效解决方案
方法1:通过透明描边强制文本按图形渲染
Safari对SVG文本的渲染逻辑与普通图形不同,添加透明描边可让浏览器将文本视为图形处理,消除变换时的闪烁:
text.my-text { /* 保留原有样式 */ dominant-baseline: middle; text-anchor: middle; pointer-events: none; /* 新增以下规则 */ paint-order: stroke fill markers; stroke: rgba(0, 0, 0, 0); stroke-width: 1px; }
方法2:拆分父组变换,单独处理文本元素
修改D3的缩放逻辑,将变换分别应用到非文本元素和文本元素上,避免父组变换导致的文本渲染异常:
function zoomed({transform}) { // 父组仅处理非文本元素 group.selectAll(':not(text)').attr("transform", transform.toString()); // 单独给文本元素应用变换 group.selectAll('text.my-text').attr("transform", transform.toString()); }
方法3:用will-change提示浏览器优化渲染
通过will-change告知浏览器提前准备文本元素的变换渲染,配合硬件加速属性:
text.my-text { will-change: transform; -webkit-transform: translate3d(0, 0, 0); }
调整后的测试代码
JavaScript
const svg = d3.select('.svg-element'); const group = svg.append('g') .attr('class', 'container-group'); group.append('circle') .attr('cx', 120) .attr('cy', 100) .attr('r', 20) .style('fill', 'pink') const ys = [80, 100, 120, 140, 160]; const text = group.selectAll('text.my-text') .data(ys) .join('text') .attr('class', 'my-text') .attr('x', (_, i) => 250 + i * 10) .attr('y', d => d) .text('A quick and lazy fox.') svg.call( d3.zoom() .extent([[0, 0], [500, 300]]) .scaleExtent([1, 8]) .on("zoom", zoomed) ); function zoomed({transform}) { group.attr("transform", transform.toString()); }
CSS
.container { width: 100%; display: flex; justify-content: center; padding: 20px 0; } .svg-element { width: 500px; height: 300px; border: 1px solid black; } text.my-text { pointer-events: none; dominant-baseline: middle; text-anchor: middle; /* 方法1的修复样式 */ paint-order: stroke fill markers; stroke: rgba(0, 0, 0, 0); stroke-width: 1px; }
HTML
<script src="https://d3js.org/d3.v7.min.js" charset="utf-8"></script> <div class="container"> <svg class="svg-element" width=300 height=300> </div>
内容的提问来源于stack exchange,提问作者Jay Wang
相关产品推荐
相关产品推荐

