We're developing a fairly complex scene with a lot of moving parts, which up until now didn't involve any SVG animation.
Everything has been smooth and performing well, until we introduced an SVG with a few dashed lines that we animated using the stroke-dashoffset property.
It makes absolutely no difference in Edge or Firefox, but in Chrome the animation of the entire scene becomes choppy and sluggish.
We've even tried both means to the same end - CSS keyframes and SMIL inside the SVG element - but both perform equally poorly.
Is there a performance trick for Chrome that we're missing?
Edit: Example
Markup:
.stream {
animation: stream 10s infinite;
}
@keyframes stream {
100% {
stroke-dashoffset: 100;
}
}
<svg version="1.0" id="streams" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 225.32 66.19" enable-background="new 0 0 225.32 66.19" xml:space="preserve">
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" d="M107.38,50.54c0,0-6.78-84.52-106.51-22.2" />
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" d="M110.49,45.31c-0.63-13.01-4.56-44.87-27.83-43.8c-27.6,1.27-37.33,39.66-38.49,60.34"/>
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" d="M180.63,59.88c-0.69-9.65-3.6-30.18-15.76-45.51C148.44-6.34,131.85,2.22,128.87,5c-2.89,2.7-12.81,7.14-14.28,42"/>
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" d="M118.59,45.41c2.4-10.18,9.9-31.97,30.87-37.59c26.03-6.98,55.13,9.32,72.02,19.37"/>
</svg>
duplicate of How can I animate infinite marker movement down an SVG path without very high CPU usage?
the real problem here are poor svg-implementations, see chrome bug
one workaround does reduce the frame-rate with a javascript animation, see the code sample
this particular case can be done with a dashed circle and css transform: rotate3d()
. but also the "GPU transforms" translate/rotate have poor performance in today's svg implementations. workaround: wrap svg code inside a <div>
and animate the div, and voila! cpu goes down to zero. related: crmarsh.com/svg-performance
const svg_elem = document.getElementById('streams')
const animateDashTime = 200 // milliseconds
let anim_dash_offset = 0
let animateDashTimer = null
function animateDashStep(){
anim_dash_offset += 1
svg_elem.setAttribute('style',
'--stroke-dashoffset: '+anim_dash_offset);
// repeat
animateDashTimer = setTimeout(
animateDashStep,
animateDashTime
)
}
// start
animateDashStep()
// stop
//clearTimeout(animateDashTimer)
<svg version="1.0" id="streams" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 225.32 66.19" enable-background="new 0 0 225.32 66.19" xml:space="preserve"
style="--stroke-dashoffset: 0"
>
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10"
stroke-dasharray="3,4"
stroke-dashoffset="var(--stroke-dashoffset)"
d="M107.38,50.54c0,0-6.78-84.52-106.51-22.2"
/>
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" stroke-dashoffset="var(--stroke-dashoffset)" d="M110.49,45.31c-0.63-13.01-4.56-44.87-27.83-43.8c-27.6,1.27-37.33,39.66-38.49,60.34"
/>
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" stroke-dashoffset="var(--stroke-dashoffset)" d="M180.63,59.88c-0.69-9.65-3.6-30.18-15.76-45.51C148.44-6.34,131.85,2.22,128.87,5c-2.89,2.7-12.81,7.14-14.28,42"/>
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" stroke-dashoffset="var(--stroke-dashoffset)" d="M118.59,45.41c2.4-10.18,9.9-31.97,30.87-37.59c26.03-6.98,55.13,9.32,72.02,19.37"/>
</svg>
You need to set the ease on your animation to linear
. Run the snippet below to see it run without that chunky slow-down.
.stream {
animation: stream 10s linear infinite;
}
@keyframes stream {
100% {
stroke-dashoffset: 100;
}
}
<svg version="1.0" id="streams" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 225.32 66.19" enable-background="new 0 0 225.32 66.19" xml:space="preserve">
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" d="M107.38,50.54c0,0-6.78-84.52-106.51-22.2" />
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" d="M110.49,45.31c-0.63-13.01-4.56-44.87-27.83-43.8c-27.6,1.27-37.33,39.66-38.49,60.34"/>
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" d="M180.63,59.88c-0.69-9.65-3.6-30.18-15.76-45.51C148.44-6.34,131.85,2.22,128.87,5c-2.89,2.7-12.81,7.14-14.28,42"/>
<path class="stream" fill="none" stroke="#000" stroke-width="1.75" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,4" d="M118.59,45.41c2.4-10.18,9.9-31.97,30.87-37.59c26.03-6.98,55.13,9.32,72.02,19.37"/>
</svg>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With