最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - SVG animations: sluggishpoor performance in Chrome - Stack Overflow

programmeradmin4浏览0评论

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
 |  Show 2 more ments

3 Answers 3

Reset to default 3

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./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>

发布评论

评论列表(0)

  1. 暂无评论