We're developing a fairly plex 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 bees 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="" xmlns: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>
We're developing a fairly plex 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 bees 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/2000/svg" xmlns:xlink="http://www.w3/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>
Share
Improve this question
edited Nov 20, 2018 at 19:33
Ted
14.9k2 gold badges42 silver badges58 bronze badges
asked Nov 20, 2018 at 18:37
GeatGeat
1,2097 silver badges19 bronze badges
7
- are you using requestAnimationFrame? – Joe Warner Commented Nov 20, 2018 at 18:39
- Got an example to reproduce? – Chris W. Commented Nov 20, 2018 at 19:03
- We're using requestAnimationFrame for any JS animations, yeah. The SVG animations use SMIL or CSS (both of which were sluggish) so it doesn't apply there. – Geat Commented Nov 20, 2018 at 19:13
- anyway you can refactor your css to js animations so you can make benefits of performance optimizations, not alot you can do with css, and especially when you're not showing examples. – Joe Warner Commented Nov 20, 2018 at 19:17
- 1 For me, it's smooth on both Chrome 69/Windows and Chromium 70/Debian, provided I wait for the initial loading processes having run their course. Does the problem continue after the page has been fully loaded? Do you have tested it with different profiles to make sure the issue isn't with some browser extension? – ccprog Commented Nov 20, 2018 at 20:15
3 Answers
Reset to default 3duplicate 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./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/2000/svg" xmlns:xlink="http://www.w3/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/2000/svg" xmlns:xlink="http://www.w3/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>
Instead of the JavaScript approach given by Mila Nautikus, you can simply use animation-timing-function: steps(n)
to achieve to the same effect. Setting n
to m * (how many stroke-dashoffset changed during an animation loop)
for a smoother animation, for example:
.stream {
animation: stream 0.5s steps(14) infinite;
}
@keyframes stream {
100% {
stroke-dashoffset: 7;
}
}
<svg version="1.0" id="streams" xmlns="http://www.w3/2000/svg" xmlns:xlink="http://www.w3/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>
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744134695a4560005.html
评论列表(0条)