OS: OSX 10.13.2
Browsers: Chrome/Firefox/Safari latest

As you can see in this gif, most of the frames animate properly. Some however have the lines "jumping" to their final values rather than being smoothly transitioned.
This animated scatter is being created from the Python API, but I suspect this is more appropriate for the js side to investigate. (Correct me if I'm wrong).
Here is the script to recreate the above chart.
Notes
import numpy as np
import colorlover as cl
from plotly.offline import plot
sim_duration = 20.0
time_inc = 0.1
line_count = 120
times = np.arange(0.0, sim_duration, time_inc)
# Setting colors for plot.
potvin_scheme = [
'rgb(115, 0, 0)',
'rgb(252, 33, 23)',
'rgb(230, 185, 43)',
'rgb(107, 211, 100)',
'rgb(52, 211, 240)',
'rgb(36, 81, 252)',
'rgb(0, 6, 130)'
]
# It's hacky but also sorta cool.
c = cl.to_rgb(cl.interp(potvin_scheme, line_count))
c = [val.replace('rgb', 'rgba') for val in c]
c = [val.replace(')', ',{})') for val in c]
def get_color(trace_index: int) -> str:
# The first and every 20th trace should be full opacity
alpha = 0.2
if trace_index == 0 or ((trace_index + 1) % 20 == 0):
alpha = 1.0
color = c[trace_index].format(alpha)
return color
# Per Motor Unit Force
start = np.ones((line_count, len(times)))
inds = np.reshape(np.arange(1.0, 41.0, 40 / len(times)), (1, len(times)))
vals = (-np.log(inds) + 4) / 0.18
vals = np.repeat(vals, line_count, axis=0)
all_array = np.ones((line_count, len(times))) * np.reshape(np.arange(0.0, 35.0, 35 / line_count), (line_count, 1))
all_array += vals # <---- COMMENT OUT TO REMOVE CURVE
data = []
annotations = []
anno_offsets = {
0: 20,
19: 30,
39: 40,
59: 45,
79: 17,
99: 56,
119: 170
}
max_y = np.amax(all_array)
for i, t in enumerate(all_array):
trace = dict(
x=times[:1],
y=t[:1],
name=i + 1,
marker=dict(
color=get_color(i)
),
mode='lines'
)
data.append(trace)
frames = []
for i in range(1, len(times), int(1 / time_inc)):
frame_data = []
for j, t in enumerate(all_array):
trace = dict(
x=times[:i],
y=t[:i],
name=j + 1,
marker=dict(
color=get_color(j)
),
mode='lines'
)
frame_data.append(trace)
frame = dict(
data=frame_data
)
frames.append(frame)
layout = dict(
title='Motor Unit Forces by Time',
yaxis=dict(
title='Motor unit force (relative to MU1 tetanus)',
range=[0, max_y],
autorange=False
),
xaxis=dict(
title='Time (s)',
range=[0, sim_duration],
autorange=False
),
updatemenus=[{
'type': 'buttons',
'buttons': [{
'args': [
None,
{'frame': {'duration': 300, 'redraw': False},
'fromcurrent': True,
'transition': {'duration': 200, 'easing': 'linear'}
}
],
'label': 'Play',
'method': 'animate'
}]
}]
)
layout['annotations'] = annotations
fig = dict(
data=data,
layout=layout,
frames=frames
)
plot(fig, filename='bug.html', validate=False)
Thanks for the report!
As per our issue guidelines:
If you don't know JavaScript and still want to help us by reporting a bug, please attach the
"data"and"layout"attributes that describe your graph and updates (if required to detect the bug). One way to retrieve your graph's data and layout attributes is by exporting your graph to Plotly Cloud. To do so, click on the _Edit in Chart Studio_ mode bar button (the 2nd one from the left by default) and follow these instructions, or watch this screencast.
... and note that the same instructions work for graphs with data, layout and a set of frames like yours.
@etpinard Data is generated and the layout is specified in the attached script. Thanks.
@iandanforth we understand that the Python code here reproduces the bug but the first step for us to work on this issue would need to be converting it to pure JavaScript anyway, which is substantially easier for you (since you already have this graph generated) than it is for us, and can also help rule out non-JavaScript root causes. That鈥檚 why we ask reporters to provide a reproduction specifically in JavaScript. Thanks for your understanding!
@alexcjohnson Thanks for the note. The output of the script is an HTML file which is 9.4M which throws an error during the export->save flow. Here is the generated file
Hmm ok, seems there are several issues here. The HTML file should help us to debug, so thanks for posting that.
I should note the 'error' on export is more of a warning due to the filesize, so I can't save/share it with my free account.
Ok. I was able to reproduce the issue (issues?) in a fairly minimal codepen: https://codepen.io/etpinard/pen/pZJZJo?editors=0010
From my observations, the animation doesn't apply transitions (i.e. a linear tween) to the lines until about the 10th frame, before the animation only redraws the line with the frame data pts. That's a bug.
Now, in https://codepen.io/etpinard/pen/QBbxpV (which behaves like the python generated file @iandanforth provided, but with less traces) there seems to be a race condition where some frames transition before others. This shouldn't happen.
@etpinard Thanks for looking into this, I really appreciate your time and effort!
Ok, after some further investigations, I don't think there's an _easy_ fix for this issue.
In brief, our current transition machinery (which make use of d3.js) doesn't allow to smoothly transition between line paths of different coordinate lengths.
Now, why does _some_ frame smoothly transition in @iandanforth's example? That's because the line point decimation algo produces lines with the same number of underlying coordinates in a few cases.
Note that by setting line.simpifly to false, all frames do not smoothly transition and the "race" condition discussed previously is gone.
I found one workaround for d3's (and plotly's :smirk: ) limitations in https://bocoup.com/blog/improving-d3-path-animation where we make all frames have the same number of coordinates. In your case, something like https://codepen.io/etpinard/pen/djoQXJ?editors=1010 (where all coordinates past the frame index our clamped to the "last" coord) with line.simplify: false should work. But unfortunately, this will require a patch in plotly.js where line.simplify: false trace need to through this block
to not have their duplicated points taken out. The above codepen with the above patch gives:

@alexcjohnson do you think patching the above line in line_points.js and documenting this "equal-length" workaround is an ok solution to the problem, or should we try to find a better way to smoothly transition line paths of different coordinate lengths?
do you think patching the above line in line_points.js and documenting this "equal-length" workaround is an ok solution to the problem
Yes, seems like line.simplify: false should mean that anyway. This would be important for other animations too, even if the number of points really is constant but there's a chance that sometimes neighboring points could match.
or should we try to find a better way to smoothly transition line paths of different coordinate lengths?
That would be great, but sounds theoretically ambiguous. How can we tell if an increase in number of points is an append, prepend, insert, or something else? All of those would imply different animations.
@iandanforth https://github.com/plotly/plotly.js/pull/2814 along with https://gist.github.com/etpinard/c14dc5b69241586bd95c2f7bf2b0f5a7 will give you a way to smoothly animate your line traces.
This is great! Again really appreciated.