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
Further animation progress and cleanup
  • Loading branch information
rreusser committed Jun 11, 2016
commit 7285a0a5c7f67844ffc91046af137410f6d42014
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[*.js]
indent_style = space
indent_size = 4
31 changes: 19 additions & 12 deletions src/components/drawing/index.js
8000
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,14 @@ 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, dir, transitionDelay, transitionCascade) {
drawing.translatePoints = function(s, xa, ya, transitionConfig, trace) {

var hasTransition = transitionConfig && (transitionConfig || {}).duration > 0;

if (hasTransition) {
var size = s.size();
}

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),
Expand All @@ -57,26 +64,26 @@ drawing.translatePoints = function(s, xa, ya, transitionDuration, transitionEasi
if(this.nodeName==='text') {
p.attr('x',x).attr('y',y);
} else {
if (isNumeric(transitionDuration) && transitionDuration > 0) {
if (hasTransition) {
var trans;
if (!dir) {
if (!transitionConfig.direction) {
trans = p.transition()
.delay(transitionDelay + transitionCascade * i)
.duration(transitionDuration)
.ease(transitionEasing)
.delay(transitionConfig.delay + transitionConfig.cascade / size * i)
.duration(transitionConfig.duration)
.ease(transitionConfig.easing)
.attr('transform', 'translate('+x+','+y+')')

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

if (trace) {
Expand All @@ -85,8 +92,8 @@ drawing.translatePoints = function(s, xa, ya, transitionDuration, transitionEasi

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

Expand Down
9 changes: 5 additions & 4 deletions src/plot_api/plot_api.js
10000
Original file line number Diff line number Diff line change
Expand Up @@ -1611,16 +1611,17 @@ Plotly.animate = function animate (gd, newData, transitionOpts, traces) {
var animateList = [];
var restyleList = [];


function doAnimations () {
var a;
var a, i, j;
for (i = 0; i < animateList.length; i++) {
a = animateList[i];
//a.module.animate(gd, a.contFull, a.newData, transitionOpts);
var basePlotModules = fullLayout._basePlotModules;
for(i = 0; i < basePlotModules.length; i++) {
basePlotModules[i].plot(gd, transitionOpts);
for(j = 0; j < basePlotModules.length; j++) {
basePlotModules[j].plot(gd, transitionOpts);
}
}

if (!transitionOpts.leadingEdgeRestyle) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, transitionOpts.duration);
Expand Down
3 changes: 3 additions & 0 deletions src/plots/cartesian/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ exports.plot = function(gd, transitionOpts) {

for(var j = 0; j < modules.length; j++) {
var _module = modules[j];

if(_module.setPositions) _module.setPositions(gd, subplotInfo);

// skip over non-cartesian trace modules
if(_module.basePlotModule.name !== 'cartesian') continue;

Expand Down
231 changes: 121 additions & 110 deletions src/traces/scatter/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,20 @@ var linePoints = require('./line_points');
module.exports = function plot(gd, plotinfo, cdscatter, group, transitionOpts) {
selectMarkers(gd, plotinfo, cdscatter);

transitionOpts = transitionOpts || {};
var transitionConfig = Lib.extendFlat({}, transitionOpts || {});
transitionConfig = Lib.extendFlat({
duration: 0,
easing: 'in-out-cubic',
cascade: 0,
delay: 0,
}, transitionConfig);

var transitionDuration = transitionOpts.duration === undefined ? 0 : transitionOpts.duration;
var transitionEasing = transitionOpts.easing === undefined ? 'in-out-cubic' : transitionOpts.easing;
var hasTransition = transitionConfig.duration > 0;

function transition (selection) {
return selection.transition()
.duration(transitionDuration)
.ease(transitionEasing);
.duration(transitionConfig.duration)
.ease(transitionConfig.easing);
}

var xa = plotinfo.x(),
Expand Down Expand Up @@ -60,8 +65,6 @@ module.exports = function plot(gd, plotinfo, cdscatter, group, transitionOpts) {

arraysToCalcdata(cdscatter);

if(!subTypes.hasLines(trace) && trace.fill === 'none') return;

var prevpath = '';
var prevtrace = trace._prevtrace;

Expand All @@ -80,6 +83,7 @@ module.exports = function plot(gd, plotinfo, cdscatter, group, transitionOpts) {
// functions for converting a point array to a path
pathfn, revpathbase, revpathfn;


// make the fill-to-zero path now, so it shows behind the line
// fill to next puts the fill associated with one trace
// grouped with the previous
Expand Down Expand Up @@ -108,119 +112,123 @@ module.exports = function plot(gd, plotinfo, cdscatter, group, transitionOpts) {
trace._nexttonext = null;
}

if (tonext) {
// This tells .style which trace to use for fill information:
tonext.datum(cdscatter);
}
if(subTypes.hasLines(trace) || trace.fill !== 'none') {

if(['hv', 'vh', 'hvh', 'vhv'].indexOf(line.shape) !== -1) {
pathfn = Drawing.steps(line.shape);
revpathbase = Drawing.steps(
line.shape.split('').reverse().join('')
);
}
else if(line.shape === 'spline') {
pathfn = revpathbase = function(pts) {
var pLast = pts[pts.length - 1];
if(pts[0][0] === pLast[0] && pts[0][1] === pLast[1]) {
// identical start and end points: treat it as a
// closed curve so we don't get a kink
return Drawing.smoothclosed(pts.slice(1), line.smoothing);
}
else {
return Drawing.smoothopen(pts, line.smoothing);
}
};
}
else {
pathfn = revpathbase = function(pts) {
return 'M' + pts.join('L');
};
}
if (tonext) {
// This tells .style which trace to use for fill information:
tonext.datum(cdscatter);
}

revpathfn = function(pts) {
// note: this is destructive (reverses pts in place) so can't use pts after this
return revpathbase(pts.reverse());
};

var segments = linePoints(cdscatter, {
xaxis: xa,
yaxis: ya,
connectGaps: trace.connectgaps,
baseTolerance: Math.max(line.width || 1, 3) / 4,
linear: line.shape === 'linear'
});
if(['hv', 'vh', 'hvh', 'vhv'].indexOf(line.shape) !== -1) {
pathfn = Drawing.steps(line.shape);
revpathbase = Drawing.steps(
line.shape.split('').reverse().join('')
);
}
else if(line.shape === 'spline') {
pathfn = revpathbase = function(pts) {
var pLast = pts[pts.length - 1];
if(pts[0][0] === pLast[0] && pts[0][1] === pLast[1]) {
// identical start and end points: treat it as a
// closed curve so we don't get a kink
return Drawing.smoothclosed(pts.slice(1), line.smoothing);
}
else {
return Drawing.smoothopen(pts, line.smoothing);
}
};
}
else {
pathfn = revpathbase = function(pts) {
return 'M' + pts.join('L');
};
}

if(segments.length) {
var pt0 = segments[0][0],
lastSegment = segments[segments.length - 1],
pt1 = lastSegment[lastSegment.length - 1];

for(var i = 0; i < segments.length; i++) {
var pts = segments[i];
thispath = pathfn(pts);
thisrevpath = revpathfn(pts);
if(!fullpath) {
fullpath = thispath;
revpath = thisrevpath;
}
else if(ownFillDir) {
fullpath += 'L' + thispath.substr(1);
revpath = thisrevpath + ('L' + revpath.substr(1));
}
else {
fullpath += 'Z' + thispath;
revpath = thisrevpath + 'Z' + revpath;
}
if(subTypes.hasLines(trace) && pts.length > 1) {
var lineJoin = tr.selectAll('.js-line').data([cdscatter]);
revpathfn = function(pts) {
// note: this is destructive (reverses pts in place) so can't use pts after this
return revpathbase(pts.reverse());
};

lineJoin.enter()
.append('path').classed('js-line', true).attr('d', thispath);
var segments = linePoints(cdscatter, {
xaxis: xa,
yaxis: ya,
connectGaps: trace.connectgaps,
baseTolerance: Math.max(line.width || 1, 3) / 4,
linear: line.shape === 'linear'
});

if(segments.length) {
var pt0 = segments[0][0],
lastSegment = segments[segments.length - 1],
pt1 = lastSegment[lastSegment.length - 1];

for(var i = 0; i < segments.length; i++) {
var pts = segments[i];
thispath = pathfn(pts);
thisrevpath = revpathfn(pts);
if(!fullpath) {
fullpath = thispath;
revpath = thisrevpath;
}
else if(ownFillDir) {
fullpath += 'L' + thispath.substr(1);
revpath = thisrevpath + ('L' + revpath.substr(1));
}
else {
fullpath += 'Z' + thispath;
revpath = thisrevpath + 'Z' + revpath;
}
if(subTypes.hasLines(trace) && pts.length > 1) {
var lineJoin = tr.selectAll('.js-line').data([cdscatter]);

transition(lineJoin).attr('d', thispath);
}
}
if(ownFillEl3) {
if(pt0 && pt1) {
if(ownFillDir) {
if(ownFillDir === 'y') {
pt0[1] = pt1[1] = ya.c2p(0, true);
}
else if(ownFillDir === 'x') {
pt0[0] = pt1[0] = xa.c2p(0, true);
}
lineJoin.enter()
.append('path').classed('js-line', true).attr('d', thispath);

// fill to zero: full trace path, plus extension of
// the endpoints to the appropriate axis
transition(ownFillEl3).attr('d', fullpath + 'L' + pt1 + 'L' + pt0 + 'Z');
} else {
// fill to self: just join the path to itself
transition(ownFillEl3).attr('d', fullpath + 'Z');
transition(lineJoin).attr('d', thispath);
}
}
}
else if(trace.fill.substr(0, 6) === 'tonext' && fullpath && prevpath) {
// fill to next: full trace path, plus the previous path reversed
if(trace.fill === 'tonext') {
// tonext: for use by concentric shapes, like manually constructed
// contours, we just add the two paths closed on themselves.
// This makes strange results if one path is *not* entirely
// inside the other, but then that is a strange usage.
transition(tonext).attr('d', fullpath + 'Z' + prevpath + 'Z');
if(ownFillEl3) {
if(pt0 && pt1) {
if(ownFillDir) {
if(ownFillDir === 'y') {
pt0[1] = pt1[1] = ya.c2p(0, true);
}
else if(ownFillDir === 'x') {
pt0[0] = pt1[0] = xa.c2p(0, true);
}

// fill to zero: full trace path, plus extension of
// the endpoints to the appropriate axis
transition(ownFillEl3).attr('d', fullpath + 'L' + pt1 + 'L' + pt0 + 'Z');
} else {
// fill to self: just join the path to itself
transition(ownFillEl3).attr('d', fullpath + 'Z');
}
}
}
else {
// tonextx/y: for now just connect endpoints with lines. This is
// the correct behavior if the endpoints are at the same value of
// y/x, but if they *aren't*, we should ideally do more complicated
// things depending on whether the new endpoint projects onto the
// existing curve or off the end of it
transition(tonext).attr('d', fullpath + 'L' + prevpath.substr(1) + 'Z');
else if(trace.fill.substr(0, 6) === 'tonext' && fullpath && prevpath) {
// fill to next: full trace path, plus the previous path reversed
if(trace.fill === 'tonext') {
// tonext: for use by concentric shapes, like manually constructed
// contours, we just add the two paths closed on themselves.
// This makes strange results if one path is *not* entirely
// inside the other, but then that is a strange usage.
transition(tonext).attr('d', fullpath + 'Z' + prevpath + 'Z');
}
else {
// tonextx/y: for now just connect endpoints with lines. This is
// the correct behavior if the endpoints are at the same value of
// y/x, but if they *aren't*, we should ideally do more complicated
// things depending on whether the new endpoint projects onto the
// existing curve or off the end of it
transition(tonext).attr('d', fullpath + 'L' + prevpath.substr(1) + 'Z');
}
}
}

trace._revpath = revpath;
}

trace._revpath = revpath;

// remove paths that didn't get used
//tr.selectAll('path:not([d])').remove();
Expand Down Expand Up @@ -254,11 +262,14 @@ module.exports = function plot(gd, plotinfo, cdscatter, group, transitionOpts) {

join.enter().append('path')
.classed('point', true)
.call(Drawing.translatePoints, xa, ya);
.call(Drawing.translatePoints, xa, ya, Lib.extendFlat(transitionConfig, {direction: 1}), trace)

join.transition()
.duration(0)
.call(Drawing.translatePoints, xa, ya, transitionDuration, transitionEasing, trace, 0, 0, 0);
.call(Drawing.translatePoints, xa, ya, Lib.extendFlat(transitionConfig, {direction: 0}), trace);

join.exit()
.call(Drawing.translatePoints, xa, ya, Lib.extendFlat(transitionConfig, {direction: -1}), trace);
}
if(showText) {
s.selectAll('g')
Expand All @@ -267,7 +278,7 @@ module.exports = function plot(gd, plotinfo, cdscatter, group, transitionOpts) {
// it gets converted to mathjax
.enter().append('g')
.append('text')
.call(Drawing.translatePoints, xa, ya, transitionDuration, transitionEasing, trace, 0, 0, 0);
.call(Drawing.translatePoints, xa, ya, Lib.extendFlat(transitionConfig, {direction: 1}), trace);
}
}
}
Expand Down
Loading
0