Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I animate infinite marker movement down an SVG path without very high CPU usage?

Tags:

css

svg

d3.js

I wish to implement flow indicators on the links of my D3 graph, as in this block.

The block uses stroke-dashoffset keyframe CSS animation to achieve the flow, and while it looks good, CPU usage sits at almost 100.

I read that you can trick some browsers into triggering GPU acceleration by including certain CSS properties, but other sources indicated that this no longer works, and certainly I couldn't see any benefit when trying to add transform: translateZ(0); (for example).

I have been investigating other options, and I tried to implement a moving marker along a line, in this style. For only one marker performance is better, but when I added multiple performance was worse.

Is there another, more performant option for animating a marker down an SVG path?

Failing another approach, I will try adding controls to stop / start the animation, but that would be a last resort.

Thanks in advance!

like image 201
goodforenergy Avatar asked Nov 17 '15 04:11

goodforenergy


People also ask

Can SVG have animations?

SVG supports the ability to change vector graphics over time, to create animated effects. SVG content can be animated in the following ways: Using SVG's animation elements [svg-animation]. SVG document fragments can describe time-based modifications to the document's elements.

Why is my SVG not animating?

One of the most common reasons why the SVG animation doesn't work is the use of <img> tags to add the SVG. The SVG might be visible on the website, but the animation will not start. You can easily fix this by replacing all <img> tags with an <object> tag.


1 Answers

It seems indeed that animating the stroke-dashoffset attribute causes a lot of calculations. The original example causes a CPU usage at around 50% when I open it in Firefox.

There's another approach that seems to give better results: manually increment the stroke-dashoffset and loop that using setInterval. Here's a proof of concept:

http://bl.ocks.org/kmandov/raw/a87de2dd49a21be9f95c/

Here's how I update the dashoffset:

var lines = d3.selectAll('.flowline');

var offset = 1; 
setInterval(function() {
  lines.style('stroke-dashoffset', offset);
  offset += 1; 
}, 50);  

I know that it doesn't look very good but it (surprisingly) performs a lot better than relying on css animations or transitions. In Firefox I now get CPU usage at about 15%.

I can imagine that this approach won't perform very well if you have a lot of links, because the update will take too long. But maybe it's a viable hack for simpler use cases where you animate linearly a fixed amount of links.

like image 85
kmandov Avatar answered Sep 24 '22 02:09

kmandov