From 41a5a83a6d2c5b82c31a9a7edd23000bd1763187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 5 Sep 2019 16:41:12 -0400 Subject: [PATCH] fix #4153 - reset loop variable in old/new transition prepare loops - this commits fixes both the `Plotly.animate` and the `Plotly.react` case. --- src/plots/plots.js | 17 ++++--- test/jasmine/tests/animate_test.js | 69 ++++++++++++++++++++++++++- test/jasmine/tests/transition_test.js | 69 +++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 10 deletions(-) diff --git a/src/plots/plots.js b/src/plots/plots.js index 705e8aa614d..b0d1ce3a70e 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -2407,26 +2407,25 @@ plots.transition = function(gd, data, layout, traces, frameOpts, transitionOpts) var xr0 = xa.range.slice(); var yr0 = ya.range.slice(); - var xr1; + var xr1 = null; + var yr1 = null; + var editX = null; + var editY = null; + if(Array.isArray(newLayout[xa._name + '.range'])) { xr1 = newLayout[xa._name + '.range'].slice(); } else if(Array.isArray((newLayout[xa._name] || {}).range)) { xr1 = newLayout[xa._name].range.slice(); } - - var yr1; if(Array.isArray(newLayout[ya._name + '.range'])) { yr1 = newLayout[ya._name + '.range'].slice(); } else if(Array.isArray((newLayout[ya._name] || {}).range)) { yr1 = newLayout[ya._name].range.slice(); } - var editX; if(xr0 && xr1 && (xr0[0] !== xr1[0] || xr0[1] !== xr1[1])) { editX = {xr0: xr0, xr1: xr1}; } - - var editY; if(yr0 && yr1 && (yr0[0] !== yr1[0] || yr0[1] !== yr1[1])) { editY = {yr0: yr0, yr1: yr1}; } @@ -2518,12 +2517,12 @@ plots.transitionFromReact = function(gd, restyleFlags, relayoutFlags, oldFullLay xa.setScale(); ya.setScale(); - var editX; + var editX = null; + var editY = null; + if(xr0[0] !== xr1[0] || xr0[1] !== xr1[1]) { editX = {xr0: xr0, xr1: xr1}; } - - var editY; if(yr0[0] !== yr1[0] || yr0[1] !== yr1[1]) { editY = {yr0: yr0, yr1: yr1}; } diff --git a/test/jasmine/tests/animate_test.js b/test/jasmine/tests/animate_test.js index 933618c4aa3..a8d265f9992 100644 --- a/test/jasmine/tests/animate_test.js +++ b/test/jasmine/tests/animate_test.js @@ -708,7 +708,6 @@ describe('Animate API details', function() { }); describe('Animating multiple axes', function() { - 'use strict'; var gd; beforeEach(function() { @@ -750,6 +749,74 @@ describe('Animating multiple axes', function() { .catch(failTest) .then(done); }); + + it('should not leak axis update from subplot to subplot', function(done) { + function _animate(frameLayout) { + return function() { + return Plotly.animate(gd, {layout: frameLayout}, { + frame: {redraw: false, duration: 10}, + transition: {duration: 10} + }); + }; + } + + function _assert(msg, exp) { + return function() { + var fullLayout = gd._fullLayout; + for(var k in exp) { + expect(fullLayout[k].range).toBeCloseToArray(exp[k], 2, msg + '| ' + k); + } + }; + } + + Plotly.plot(gd, [{ + x: [0.1, 0.2, 0.3], + y: [0.4, 0.5, 0.6], + }, { + x: [0.2, 0.3, 0.4], + y: [0.5, 0.6, 0.7], + xaxis: 'x2', + yaxis: 'y2', + }, { + x: [0.3, 0.5, 0.7], + y: [0.7, 0.2, 0.2], + xaxis: 'x3', + yaxis: 'y3', + }], { + grid: {rows: 1, columns: 3, pattern: 'independent'}, + showlegend: false + }) + .then(_assert('base', { + xaxis: [0.0825, 0.3174], xaxis2: [0.1825, 0.417], xaxis3: [0.265, 0.7349], + yaxis: [0.385, 0.614], yaxis2: [0.485, 0.714], yaxis3: [0.163, 0.7366] + })) + .then(_animate({ + xaxis: {range: [-10, 10]}, + yaxis: {range: [-10, 10]} + })) + .then(_assert('after xy range animate', { + xaxis: [-10, 10], xaxis2: [0.1825, 0.417], xaxis3: [0.265, 0.7349], + yaxis: [-10, 10], yaxis2: [0.485, 0.714], yaxis3: [0.163, 0.7366] + })) + .then(_animate({ + xaxis2: {range: [-20, 20]}, + yaxis2: {range: [-20, 20]} + })) + .then(_assert('after x2y2 range animate', { + xaxis: [-10, 10], xaxis2: [-20, 20], xaxis3: [0.265, 0.7349], + yaxis: [-10, 10], yaxis2: [-20, 20], yaxis3: [0.163, 0.7366] + })) + .then(_animate({ + xaxis3: {range: [-30, 30]}, + yaxis3: {range: [-30, 30]} + })) + .then(_assert('after x3y3 range animate', { + xaxis: [-10, 10], xaxis2: [-20, 20], xaxis3: [-30, 30], + yaxis: [-10, 10], yaxis2: [-20, 20], yaxis3: [-30, 30] + })) + .catch(failTest) + .then(done); + }); }); describe('non-animatable fallback', function() { diff --git a/test/jasmine/tests/transition_test.js b/test/jasmine/tests/transition_test.js index 9667086a58a..96fdb32857c 100644 --- a/test/jasmine/tests/transition_test.js +++ b/test/jasmine/tests/transition_test.js @@ -1028,4 +1028,73 @@ describe('Plotly.react transitions:', function() { .catch(failTest) .then(done); }); + + it('should not leak axis update from subplot to subplot', function(done) { + function _react(modifs) { + return function() { + for(var k in modifs) { + gd.layout[k] = modifs[k]; + } + return Plotly.react(gd, gd.data, gd.layout); + }; + } + + function _assert(msg, exp) { + return function() { + var fullLayout = gd._fullLayout; + for(var k in exp) { + expect(fullLayout[k].range).toBeCloseToArray(exp[k], 2, msg + '| ' + k); + } + }; + } + + Plotly.plot(gd, [{ + x: [0.1, 0.2, 0.3], + y: [0.4, 0.5, 0.6], + }, { + x: [0.2, 0.3, 0.4], + y: [0.5, 0.6, 0.7], + xaxis: 'x2', + yaxis: 'y2', + }, { + x: [0.3, 0.5, 0.7], + y: [0.7, 0.2, 0.2], + xaxis: 'x3', + yaxis: 'y3', + }], { + grid: {rows: 1, columns: 3, pattern: 'independent'}, + showlegend: false, + transition: {duration: 10} + }) + .then(_assert('base', { + xaxis: [0.0825, 0.3174], xaxis2: [0.1825, 0.417], xaxis3: [0.265, 0.7349], + yaxis: [0.385, 0.614], yaxis2: [0.485, 0.714], yaxis3: [0.163, 0.7366] + })) + .then(_react({ + xaxis: {range: [-10, 10]}, + yaxis: {range: [-10, 10]} + })) + .then(_assert('after xy range transition', { + xaxis: [-10, 10], xaxis2: [0.1825, 0.417], xaxis3: [0.265, 0.7349], + yaxis: [-10, 10], yaxis2: [0.485, 0.714], yaxis3: [0.163, 0.7366] + })) + .then(_react({ + xaxis2: {range: [-20, 20]}, + yaxis2: {range: [-20, 20]} + })) + .then(_assert('after x2y2 range transition', { + xaxis: [-10, 10], xaxis2: [-20, 20], xaxis3: [0.265, 0.7349], + yaxis: [-10, 10], yaxis2: [-20, 20], yaxis3: [0.163, 0.7366] + })) + .then(_react({ + xaxis3: {range: [-30, 30]}, + yaxis3: {range: [-30, 30]} + })) + .then(_assert('after x3y3 range transition', { + xaxis: [-10, 10], xaxis2: [-20, 20], xaxis3: [-30, 30], + yaxis: [-10, 10], yaxis2: [-20, 20], yaxis3: [-30, 30] + })) + .catch(failTest) + .then(done); + }); });