I notice that applying CSS transform on SVG groups would cause their children text elements to flicker in Safari. The transformation of other elements looks smooth in Safari. The transformation of all children looks smooth in Firefox or Chrome.
See below videos for example. The code is attached at the end of this post and also at https://codepen.io/xiaohk/pen/yLqOZXx.
I found several related questions:
However, all the solutions do not work for my problem. For example, I tried to set -webkit-transform-style:preserve-3d;
, -webkit-transform: translateZ(0);
, and -webkit-filter: opacity(1);
.
Any suggestions are appreciated, thank you!
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());
}
.container {
width: 100%;
display: flex;
justify-content: center;
padding: 20px 0;
-webkit-transform-style:preserve-3d;
-webkit-filter: opacity(1);
}
.svg-element {
width: 500px;
height: 300px;
border: 1px solid black;
}
g.container-group {
-webkit-backface-visibility: hidden;
}
text.my-text {
-webkit-transform-style:preserve-3d;
-webkit-transform: translateZ(0);
pointer-events: none;
dominant-baseline: middle;
text-anchor: middle;
}
<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>
Add text-rendering: geometricPrecision;
that will stop Safari from adjusting the font kerning to best display the text at each scale.