8000 [DO NOT MERGE] Animations by rreusser · Pull Request #550 · plotly/plotly.js · GitHub
[go: up one dir, main page]

Skip to content

[DO NOT MERGE] Animations #550

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

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
54bf57c
First cut at animations
rreusser May 18, 2016
c3517c2
Slightly ugly hack to animate point styles
rreusser May 31, 2016
dba188b
Merge remote-tracking branch 'upstream/master' into animations
rreusser Jun 2, 2016
2eae93a
Remove stray markTime
rreusser Jun 2, 2016
e9bcf90
A method to clone input traces
rreusser Jun 2, 2016
5497e7d
Make animations promise-based
rreusser Jun 8, 2016
c159dae
Non-working commit in the right direction...
rreusser Jun 8, 2016
1449cc5
Partial trace refactor
rreusser Jun 9, 2016
99b4bed
Scattertrace element persistence cleanup
rreusser Jun 10, 2016
7285a0a
Further animation progress and cleanup
rreusser Jun 11, 2016
8dc302c
Scatter trace optimization
rreusser Jun 12, 2016
5a624de
Scatter trace optimization
rreusser Jun 12, 2016
d580df3
Merge branch 'animations' of github.com:rreusser/plotly.js into anima…
rreusser Jun 13, 2016
81e2182
Refactor scatter traces
rreusser Jun 14, 2016
82071e3
Refactor scatter traces
rreusser Jun 14, 2016
710de7f
Merge branch 'animations' of github.com:rreusser/plotly.js into anima…
rreusser Jun 14, 2016
48e9b29
Merge remote-tracking branch 'upstream/master' into animations
rreusser Jun 14, 2016
aa19ac0
Add build
rreusser Jun 14, 2016
821c57e
Object persistence for error bars
rreusser Jun 16, 2016
a655a4b
Error bar transitions
rreusser Jun 17, 2016
c978b46
First cut at scale transitions
rreusser Jun 20, 2016
51672d8
Undo build
rreusser Jun 20, 2016
31f4f1b
Merge remote-tracking branch 'upstream/master' into animations
rreusser Jun 20, 2016
5c5c715
Animation interrupts
rreusser Jun 20, 2016
b75280f
Remove linepoint override
rreusser Jun 21, 2016
990787e
Removed unused logic
rreusser Jun 21, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Make animations promise-based
  • Loading branch information
rreusser committed Jun 8, 2016
commit 5497e7dd2312cf2613d941ce757e5348ea815db1
43 changes: 33 additions & 10 deletions src/components/drawing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ drawing.setRect = function(s, x, y, w, h) {
s.call(drawing.setPosition, x, y).call(drawing.setSize, w, h);
};

drawing.translatePoints = function(s, xa, ya, transitionDuration, transitionEasing, trace) {
s.each(function(d) {
drawing.translatePoints = function(s, xa, ya, transitionDuration, transitionEasing, trace, dir, transitionDelay, transitionCascade) {
s.each(function(d, i) {
// put xp and yp into d if pixel scaling is already done
var x = d.xp || xa.c2p(d.x),
y = d.yp || ya.c2p(d.y),
Expand All @@ -57,16 +57,39 @@ drawing.translatePoints = function(s, xa, ya, transitionDuration, transitionEasi
if(this.nodeName==='text') {
p.attr('x',x).attr('y',y);
} else {
var join = p;
if (isNumeric(transitionDuration) && transitionDuration > 0) {
var trans = p.transition()
.duration(transitionDuration)
.ease(transitionEasing)
.attr('transform', 'translate('+x+','+y+')')

if (trace) {
trans.call(drawing.pointStyle, trace)
var trans;
if (!dir) {
trans = p.transition()
.delay(transitionDelay + transitionCascade * i)
.duration(transitionDuration)
.ease(transitionEasing)
.attr('transform', 'translate('+x+','+y+')')

if (trace) {
trans.call(drawing.pointStyle, trace)
}
} else if (dir === -1) {
trans = p.style('opacity', 1)
.transition()
.duration(transitionDuration)
.ease(transitionEasing)
.style('opacity', 0)
.remove();
} else if (dir === 1) {
trans = p.attr('transform', 'translate('+x+','+y+')')

if (trace) {
trans.call(drawing.pointStyle, trace)
}

trans.style('opacity', 0)
.transition()
.duration(transitionDuration)
.ease(transitionEasing)
.style('opacity', 1)
}

} else {
p.attr('transform', 'translate('+x+','+y+')');
}
Expand Down
127 changes: 85 additions & 42 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -839,13 +839,14 @@ Plotly.newPlot = function(gd, data, layout, config) {
return Plotly.plot(gd, data, layout, config);
};

function doCalcdata(gd) {
function doCalcdata(gd, traces) {
var axList = Plotly.Axes.list(gd),
fullData = gd._fullData,
fullLayout = gd._fullLayout;

var i, trace, module, cd;

var oldCalcdata = (gd.calcdata || []).slice(0);
var calcdata = gd.calcdata = new Array(fullData.length);

// extra helper variables
Expand All @@ -870,6 +871,13 @@ function doCalcdata(gd) {
}

for(i = 0; i < fullData.length; i++) {
// If traces were specified and this trace was not included, then transfer it over from
// the old calcdata:
if (Array.isArray(traces) && traces.indexOf(i) === -1) {
calcdata[i] = oldCalcdata[i];
continue;
}

trace = fullData[i];
module = trace._module;
cd = [];
Expand Down Expand Up @@ -1521,7 +1529,18 @@ Plotly.moveTraces = function moveTraces(gd, currentIndices, newIndices) {
// 4. doCalcdata
// 5. begin animation
Plotly.animate = function animate (gd, newData, transitionOpts, traces) {
var i, newTraceData, curData, value;
var i, newTraceData, curData, value, traceIdx;

if (!Array.isArray(newData)) {
Lib.warn('Animate fail. newData must be an array of traces');
return Promise.reject();
}

transitionOpts = transitionOpts || {};
t 8000 ransitionOpts.duration = transitionOpts.duration === undefined ? 250 : transitionOpts.duration;
transitionOpts.easing = transitionOpts.easing === undefined ? 'cubic-in-out' : transitionOpts.easing;
transitionOpts.cascade = transitionOpts.cascade === undefined ? 0 : transitionOpts.cascade;
transitionOpts.leadingEdgeRestyle = transitionOpts.leadingEdgeRestyle === undefined ? false : transitionOpts.leadingEdgeRestyle;

gd = getGraphDiv(gd);

Expand All @@ -1532,30 +1551,58 @@ Plotly.animate = function animate (gd, newData, transitionOpts, traces) {

cloneTraceDefinitions(gd);

var animatedTraces = [];

for (i = 0; i < traces.length; i++) {
var traceIdx = traces[i];
var trace = gd._fullData[traceIdx];
var module = trace._module;

if (!module.animate) {
continue;
}

animatedTraces.push(traceIdx);

newTraceData = newData[i];
curData = gd.data[traces[i]];
//var trace = gd._fullData[traces[i]];

for (var ai in newTraceData) {
var value = newTraceData[ai];
Lib.nestedProperty(curData, ai).set(value);
}
}

// Placeholder for more general transfer of data:
for (var i = 0; i < traces.length; i++) {
if (gd.data[traces[i]].marker && gd.data[traces[i]].marker.size) {
gd._fullData[traces[i]].marker.size = gd.data[traces[i]].marker.size

var traceIdx = traces[i];
if (gd.data[traceIdx].marker && gd.data[traceIdx].marker.size) {
gd._fullData[traceIdx].marker.size = gd.data[traceIdx].marker.size
}
gd._fullData[traces[i]].x = gd.data[traces[i]].x;
gd._fullData[traces[i]].y = gd.data[traces[i]].y;
gd._fullData[traceIdx].x = gd.data[traceIdx].x;
gd._fullData[traceIdx].y = gd.data[traceIdx].y;
gd._fullData[traceIdx].z = gd.data[traceIdx].z;
gd._fullData[traceIdx].key = gd.data[traceIdx].key;
}

doCalcdata(gd);
doCalcdata(gd, animatedTraces);

var animateList = [];
var restyleList = [];

function doAnimations () {
var a;
for (i = 0; i < animateList.length; i++) {
a = animateList[i];
a.module.animate(gd, a.contFull, a.newData, transitionOpts);
}
if (!transitionOpts.leadingEdgeRestyle) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, transitionOpts.duration);
});
}
}

for (var i = 0; i < traces.length; i++) {
var trace = gd._fullData[traces[i]];
for (var i = 0; i < animatedTraces.length; i++) {
var trace = gd._fullData[animatedTraces[i]];
var module = trace._module;
var cd = [];

Expand All @@ -1579,50 +1626,46 @@ Plotly.animate = function animate (gd, newData, transitionOpts, traces) {
}

for (i = 0; i < traces.length; i++) {
var traceIdx = traces[i];

var idx = traces[i];

var cont = gd.data[idx];
var contFull = gd._fullData[idx];
var cont = gd.data[traceIdx];
var contFull = gd._fullData[traceIdx];
var module = contFull._module;

if (module.animate) {
module.animate(gd, contFull, newData[i], transitionOpts);
}
}

/*
for(var i = 0; i < gd.calcdata.length; i++) {
gd.calcdata[i][0].trace = gd._fullData[i];
}

var seq;
seq = [Plots.previousPromises];

seq.push(function doAnimate () {
for (var i = 0; i < traces.length; i++) {
//var cont = gd.data[traces[i]];
var trace = gd._fullData[traces[i]];
var mod = trace._module;
animateList.push({
module: module,
contFull: contFull,
newData: newData[i]
});
} else {
var thisTrace = [traceIdx];
var thisUpdate = {};

if (mod.animate) {
mod.animate(gd, trace, data[i], transitionOpts);
for (ai in newData[i]) {
thisUpdate[ai] = [newData[i][ai]];
}

restyleList.push((function (md, data, traces) {
return function () {
return Plotly.restyle(gd, data, traces);
}
}(module, thisUpdate, [traceIdx])));
}
return Plots.previousPromises(gd);
});
}

var seq = [Plots.previousPromises];
seq.push(doAnimations);
seq = seq.concat(restyleList);

var plotDone = Lib.syncOrAsync(seq, gd);

if(!plotDone || !plotDone.then) plotDone = Promise.resolve();

return plotDone.then(function() {
gd.emit('plotly_beginanimate', [traces]);
gd.emit('plotly_animate', []);
return gd;
});
*/


}

// -----------------------------------------------------
Expand Down
53 changes: 50 additions & 3 deletions src/traces/scatter/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module.exports = function animate (gd, trace, data, opts) {
opts = opts || {};
var transitionDuration = isNumeric(opts.duration) ? opts.duration : 250;
var transitionEasing = !!opts.easing ? opts.easing : 'cubic-in-out';
var transitionCascade = !!opts.cascade ? opts.cascade : 0;

//window.scattertraces = plotinfo.plot.select('.scatterlayer')

Expand Down Expand Up @@ -227,6 +228,16 @@ module.exports = function animate (gd, trace, data, opts) {
return d.filter(function(v) { return v.vis; });
}

function keyFunc (d) {
return d.key;
}

function getKeyFunc(trace) {
if (trace.key) {
return keyFunc;
}
}

scattertraces.select('g.points')
.each(function(d) {
var trace = d[0].trace,
Expand All @@ -237,11 +248,47 @@ module.exports = function animate (gd, trace, data, opts) {
if((!showMarkers && !showText) || trace.visible !== true) s.remove();
else {
if(showMarkers) {
s.selectAll('path.point')
.data(trace.marker.maxdisplayed ? visFilter : Lib.identity)
.call(Drawing.translatePoints, xa, ya, transitionDuration, transitionEasing, trace);
var selection = s.selectAll('path.point')
.data(trace.marker.maxdisplayed ? visFilter : Lib.identity, getKeyFunc(trace))

//console.log('d:', d.length);
//console.log('transitionCascade:', transitionCascade);
selection.call(Drawing.translatePoints, xa, ya, transitionDuration, transitionEasing, trace, null, 0, transitionCascade / d.length);

var enter = selection.enter().append('path')
.classed('point', true)
.call(Drawing.translatePoints, xa, ya, transitionDuration, transitionEasing, trace, 1)

selection.exit()
.call(Drawing.translatePoints, xa, ya, transitionDuration, transitionEasing, trace, -1)
}
}
});

};

/*
window.gd = gd;

scattertraces.select('g.points')
.each(function(d) {
var trace = d[0].trace,
s = d3.select(this),
showMarkers = subTypes.hasMarkers(trace),
showText = subTypes.hasText(trace);

if((!showMarkers && !showText) || trace.visible !== true) s.remove();
else {
if(showMarkers) {
var selection = s.selectAll('path.point')
.data(trace.marker.maxdisplayed ? visFilter : Lib.identity, getKeyFunc(trace));

selection.call(Drawing.translatePoints, xa, ya, transitionDuration, transitionEasing, trace);

selection.enter().append('path')
.classed('point', true)
.call(Drawing.translatePoints, xa, ya);
}
}
});
};*/
4 changes: 4 additions & 0 deletions src/traces/scatter/calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ module.exports = function calc(gd, trace) {
for(i = 0; i < serieslen; i++) {
cd[i] = (isNumeric(x[i]) && isNumeric(y[i])) ?
{x: x[i], y: y[i]} : {x: false, y: false};

if (trace.key && trace.key[i]) {
cd[i].key = trace.key[i];
}
}

// this has migrated up from arraysToCalcdata as we have a reference to 's' here
Expand Down
1 change: 1 addition & 0 deletions src/traces/scatter/defaults.js
DEA8
Original file line number Diff line numberDiff line change
Expand Up @@ -36,6 +36,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
return;
}

coerce('key');
coerce('text');
coerce('mode', defaultMode);

Expand Down
12 changes: 11 additions & 1 deletion src/traces/scatter/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,16 @@ module.exports = function plot(gd, plotinfo, cdscatter) {
return d.filter(function(v) { return v.vis; });
}

function keyFunc (d) {
return d.key;
}

function getKeyFunc(trace) {
if (trace.key) {
return keyFunc;
}
}

scattertraces.append('g')
.attr('class', 'points')
.each(function(d) {
Expand All @@ -209,7 +219,7 @@ module.exports = function plot(gd, plotinfo, cdscatter) {
else {
if(showMarkers) {
s.selectAll('path.point')
.data(trace.marker.maxdisplayed ? visFilter : Lib.identity)
.data(trace.marker.maxdisplayed ? visFilter : Lib.identity, getKeyFunc(trace))
.enter().append('path')
.classed('point', true)
.call(Drawing.translatePoints, xa, ya);
Expand Down
0