How to draw animated(progressing) trend lines?

Hi there,
can anyone guide me on how to use animations to draw progress lines? I want to show the development of some value across time using a slider animated scatter plot. Additionally to the animated scatter point I want to keep track of the direction of movement by showing a developmental curve or trend line which should grow as the slider moves through time.

Has anyone ever done something similar or could give me a hint on how to best do it? It would also be of great help, if somebody knows how to modify the fading out of points through animations in a pointwise manner e.g. to have some points fading out slower than others.

Any help is highly appreciated.
Thank you,
Cheers, Lisa

Great question, @silly_lily!

Here’s a few different approaches.

Dash animation

The easiest trick is to animate SVG dash properties using this trick. It makes for a quick/easy effect but requires knowing the length of the line in pixels and has no relation to actual data values, which basically makes it a non-starter.

Using frames

A better solution is to use frames to enumerate every visual state of the plot, then use a slider to switch between them. You’ll notice on the last couple lines that I’ve enumerated every possible slice of the data, from [0] to [0, 0.02, ..., 1]. That uses O(n^2) memory, which is pretty silly, though it does work. I’ve also used the id property. If you’re familiar with d3, this gets applied to the points as the key, which is not strictly necessary in this particular example, but which is generally a good idea when animating points in order to enforce object constancy.

Using frames with the filter transform

An optimization in order to avoid enumerating every possible slice is to use the filter transform to restrict the plotted range. Then, instead of changing the dataset for each frame, you can just change the range that gets plotted. In this example, each frame now just changes the value attribute of the filter transform. Please note that transforms are currently experimental and so are not yet documented (at least in the official docs. You can find the documentation here). The filter transform is stable and unlikely to change, but it’s not currently accessible from the python API. (I looove it though, so if you’re using plotly.js, I’d recommend it.)

Frames + filter + transition

The examples above have about a hundred data points so that I’ve disabled transitions. If you have just a few data points, it may look nicer to keep them. This example adds a finite transition duration. You’ll notice that the path doesn’t animate very nicely. That’s a result of the way SVG animates paths containing a different number of points, so unfortunately there’s not much to be done about that without a significant amount of work (it’s why people usually use the dash animation trick above to accomplish the look of a hand-drawn path). I’ve also included line: {simplify: false} when using transitions since plotly’s line simplification algorithm (it collapses lines connecting collinear points into a single segment) causes undesirable artifacts.

(One final caveat: I did just notice a bug in which the line opacity is not updated after restarting the last example. Looking into that now.)

I know that’s a lot if information. I’ve left the examples on the more feature-complete side rather than paring them down to the minimal code so that hopefully they’re close to what’s realistically needed for these to work well. Please let me know if you need clarification or if the effect is not quite the same as what you’re after.

  • Ricky
2 Likes

First of all, thank you so much @ricky! Thanks for such an elaborate and helpful answer :slight_smile: I really appreciate that you took so much time putting together example code for all the different options.
Luckily, I am using plotly.js, so I think I will go for the option using the transforms field, as that seems like the cleanest and most straight forward option to me.
If i run into any trouble I will happilly get back to you.
Cheers an thanks again,
Lisa

1 Like

Is there an updated way to do this now with the transitions API - particularly in python?