-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[WIP] Frame + Animate API #717
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
f3fee88
f50c295
3054cb5
fb04b65
28be237
3e18a98
01b9287
42467ec
0542213
cdfec13
c7be054
e4363a2
2fd9c26
b4a553b
aec44c6
e031c27
bd949e6
9132eb6
a4e8282
86ca5d6
dd995a9
cef8bd5
2fb95a7
bf2aeec
bf079e9
bb8893f
8717877
d5a8834
34b0ca3
f218e09
8f4e11e
30a3fbe
c7a68e7
e762bf4
79e6e4b
feb7636
ff37557
1086023
977afdd
246f815
db8a1c5
bc7fe74
48eec0c
85c2e20
6376166
10a655d
5904af2
c09cbb3
e1f6818
9e2f251
4e2761c
763485c
8fc47ef
c9a6549
2102d02
a992b59
0aab643
d7e4e1a
b39f221
1767a73
c2e1710
9ea6850
bcb3ce2
78b37e2
57fe960
f483788
d2d7099
ea7c037
9773720
17529ab
9955625
93eeaa8
9643811
7e2e2d8
2cecc66
fd5a3bc
13053a3
15b47f6
e887faa
f2ffa2a
2b0c537
fb87b42
8cf4395
99ee7d9
bcd2fbf
7319c83
248736e
6afc339
6e426e7
0180730
1166ac7
3ee4bf5
085203d
266f21a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
## Top-level Plotly API methods | ||
|
||
#### `Plotly.transition(gd, data, layout[, traceIndices[, config]])` | ||
Transition (eased or abruptly if desired) to a new set of data. Knows nothing about the larger state of transitions and frames; identically a 'transition the plot to look like X over Y ms' command. | ||
|
||
**Parameters**: | ||
- `data`: an *array* of *objects* containing trace data, e.g. `[{x: [1, 2, 3], 'lines.color': 'red'}, {y: [7,8]}]`, mapped to traces. | ||
- `layout`: layout properties to which to transition, probably mostly just axis ranges | ||
- `traceIndices`: a mapping between the items of `data` and the trace indices, e.g. `[0, 2]`. If omitted, is inferred from semantics like for `restyle`—which means maybe affecting all traces? | ||
- `config`: object containing transition configuration, including: | ||
- `duration`: duration in ms of transition | ||
- `ease`: d3 easing function, e.g. `elastic-in-out` | ||
- `delay`: delay until animation; not so useful, just very very easy to pass to d3 | ||
- `cascade`: transition points in sequence for a nice visual effect. Maybe just leave out. Kind of a common visual effect for eye candy purposes. Very easy. Can leave out if it leads to weird corner cases. See: http://rickyreusser.com/animation-experiments/#object-constancy | ||
|
||
**Returns**: promise that resolves when animation begins or rejects if config is invalid. | ||
|
||
**Events**: | ||
- `plotly_starttransition` | ||
- `plotly_endtransition` | ||
|
||
<hr> | ||
|
||
#### `Plotly.animate(gd, frame[, config])` | ||
Transition to a keyframe. Animation sequence is: | ||
|
||
1. Compute the requested frame | ||
2. Separate animatable and non-animatable properties into separate objects | ||
3. Mark exactly what needs to happen. This includes transitions vs. non-animatable properties, whether the axis needs to be redrawn (`needsRelayout`?), and any other optimizations that seem relevant. Since for some cases very simple updates may be coming through at up to 60fps, cutting out work here could be fairly important. | ||
|
||
**Parameters**: | ||
- `frame`: name of the frame to which to animate | ||
- `config`: see `.transition`. | ||
|
||
**Returns**: promise that resolves when animation begins or rejects if config is invalid. | ||
|
||
**Events**: | ||
- `plotly_startanimation` | ||
- `plotly_endanimation` | ||
|
||
<hr> | ||
|
||
#### `Plotly.addFrames(gd, frames[, frameIndices])` | ||
Add or overwrite frames. New frames are appended to current frame list. | ||
|
||
**Parameters** | ||
- `frames`: an array of objects containing any of `name`, `data`, `layout` and `traceIndices` fields as specified above. If no name is provided, a unique name (e.g. `frame 7`) will be assigned. If the frame already exists, then its definition is overwritten. | ||
- `frameIndices`: optional array of indices at which to insert the given frames. If indices are omitted or a specific index is falsey, then frame is appended. | ||
|
||
**Returns**: Promise that resolves on completion. (In this case, that's synchronously and mainly for the sake of API consistency.) | ||
|
||
<hr> | ||
|
||
#### `Plotly.deleteFrames(gd, frameIndices)` | ||
Remove frames by frame index. | ||
|
||
**Parameters**: | ||
- `frameIndices`: an array of integer indices of the frames to be removed. | ||
|
||
**Returns**: Promise that resolves on completion (which here means synchronously). | ||
|
||
<hr> | ||
|
||
## Frame definition | ||
|
||
Frames are defined similarly to mirror the input format, *not* that of `Plotly.restyle`. The easiest way to explain seems to be via an example that touches all features: | ||
|
||
```json | ||
{ | ||
"data": [{ | ||
"x": [1, 2, 3], | ||
"y": [4, 5, 6], | ||
"identifiers": ["China", "Pakistan", "Australia"], | ||
"lines": { | ||
"color": "red" | ||
} | ||
}, { | ||
"x": [1, 2, 3], | ||
"y": [3, 8, 9], | ||
"markers": { | ||
"color": "red" | ||
} | ||
}], | ||
"layout": { | ||
"slider": { | ||
"visible": true, | ||
"plotly_method": "animate", | ||
"args": ["$value", {"duration": 500}] | ||
}, | ||
"slider2": { | ||
"visible": true, | ||
"plotly_method": "animate", | ||
"args": ["$value", {"duration": 500}] | ||
} | ||
}, | ||
"frames": [ | ||
{ | ||
"name": "base", | ||
"y": [4, 5, 7], | ||
"identifiers": ["China", "Pakistan", "Australia"], | ||
}, { | ||
"name": "1960", | ||
"data": [{ | ||
"y": [1, 2, 3], | ||
"identifiers": ["China", "Pakistan", "Australia"], | ||
}], | ||
"layout": { | ||
"xaxis": {"range": [7, 3]}, | ||
"yaxis": {"range": [0, 5]} | ||
}, | ||
"baseFrame": "base", | ||
"traceIndices": [0] | ||
}, { | ||
"name": "1965", | ||
"data": [{ | ||
"y": [5, 3, 2], | ||
"identifiers": ["China", "Pakistan", "Australia"], | ||
}], | ||
"layout": { | ||
"xaxis": {"range": [7, 3]}, | ||
"yaxis": {"range": [0, 5]} | ||
}, | ||
"baseFrame": "base", | ||
"traceIndices": [0] | ||
} | ||
] | ||
} | ||
``` | ||
|
||
Notes on JSON: | ||
- `identifiers` is used as a d3 `key` argument. | ||
- `baseFrame` is merged… recursively? non-recursively? We'll see. Not a crucial implementation choice. | ||
- `frames` seems maybe best stored at top level. Or maybe best on the object. If on the object, `Plotly.plot` would have to be variadic (probably), accepting `Plotly.plot(gd, data, layout[, frames], config)`. That's backward-compatible but a bit ugly. If not on the object, then it would have to be shoved into `layout` (except how, because it's really awkward place in `layout`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/** | ||
* Copyright 2012-2016, Plotly, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
var extend = require('./extend'); | ||
|
||
/* | ||
* Merge two keyframe specifications, returning in a third object that | ||
* can be used for plotting. | ||
* | ||
* @param {object} target | ||
* An object with data, layout, and trace data | ||
* @param {object} source | ||
* An object with data, layout, and trace data | ||
* | ||
* Returns: a third object with the merged content | ||
*/ | ||
module.exports = function mergeKeyframes(target, source) { | ||
var result; | ||
|
||
result = extend.extendDeep({}, target); | ||
result = extend.extendDeep(result, source); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm. Do we want to merge attributes and data arrays? I'd vote for merging attributes, and overriding data arrays. Does that make sense to you @rreusser ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. This was a quick placeholder while avoiding any complexity. Need to think further about it, but at a glance, agreed. |
||
|
||
return result; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rreusser oops ... two
Plotly.animate
got in.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed & removed
renameFrame