diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 9179a2d686c..511b02e9b21 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -152,7 +152,13 @@ function plot(gd, data, layout, config) { fullLayout._replotting = true; // make or remake the framework if we need to - if(graphWasEmpty) makePlotFramework(gd); + if(graphWasEmpty || fullLayout._shouldCreateBgLayer) { + makePlotFramework(gd); + + if(fullLayout._shouldCreateBgLayer) { + delete fullLayout._shouldCreateBgLayer; + } + } // polar need a different framework if(gd.framework !== makePlotFramework) { diff --git a/src/plots/plots.js b/src/plots/plots.js index 309e1edbe43..13e49262d05 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -482,6 +482,20 @@ plots.supplyDefaults = function(gd, opts) { // clean subplots and other artifacts from previous plot calls plots.cleanPlot(newFullData, newFullLayout, oldFullData, oldFullLayout); + var hadGL2D = !!(oldFullLayout._has && oldFullLayout._has('gl2d')); + var hasGL2D = !!(newFullLayout._has && newFullLayout._has('gl2d')); + var hadCartesian = !!(oldFullLayout._has && oldFullLayout._has('cartesian')); + var hasCartesian = !!(newFullLayout._has && newFullLayout._has('cartesian')); + var hadBgLayer = hadCartesian || hadGL2D; + var hasBgLayer = hasCartesian || hasGL2D; + if(hadBgLayer && !hasBgLayer) { + // remove bgLayer + oldFullLayout._bgLayer.remove(); + } else if(hasBgLayer && !hadBgLayer) { + // create bgLayer + newFullLayout._shouldCreateBgLayer = true; + } + // clear selection outline until we implement persistent selection, // don't clear them though when drag handlers (e.g. listening to // `plotly_selecting`) update the graph. diff --git a/test/jasmine/tests/plot_api_react_test.js b/test/jasmine/tests/plot_api_react_test.js index 1050c7225fa..36ab6694643 100644 --- a/test/jasmine/tests/plot_api_react_test.js +++ b/test/jasmine/tests/plot_api_react_test.js @@ -937,6 +937,192 @@ describe('resizing with Plotly.relayout and Plotly.react', function() { }); }); +describe('clear bglayer react', function() { + var x = [1]; + var y = [2]; + var z = [3]; + + var gd; + + beforeEach(function() { + gd = createGraphDiv(); + }); + + afterEach(destroyGraphDiv); + + function hasBgRect() { + var bgLayer = d3.selectAll('.bglayer .bg'); + return bgLayer[0][0] !== undefined; // i.e. background rect + } + + it('clear plot background when react from cartesian to gl3d & back', function(done) { + Plotly.newPlot(gd, { + data: [{ type: 'scatter', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'green' } + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('green'); + expect(hasBgRect()).toBe(true); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter3d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'red' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe(undefined); + expect(hasBgRect()).toBe(false); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'green' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('green'); + expect(hasBgRect()).toBe(true); + }) + .catch(failTest) + .then(done); + }); + + it('clear plot background when react from gl2d to gl3d & back', function(done) { + Plotly.newPlot(gd, { + data: [{ type: 'scatter2d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'green' } + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('green'); + expect(hasBgRect()).toBe(true); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter3d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'red' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe(undefined); + expect(hasBgRect()).toBe(false); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter2d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'green' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('green'); + expect(hasBgRect()).toBe(true); + }) + .catch(failTest) + .then(done); + }); + + it('create plot background when react from gl3d to gl2d & back', function(done) { + Plotly.newPlot(gd, { + data: [{ type: 'scatter3d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'red' } + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe(undefined); + expect(hasBgRect()).toBe(false); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter2d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'green' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('green'); + expect(hasBgRect()).toBe(true); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter3d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'red' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe(undefined); + expect(hasBgRect()).toBe(false); + }) + .catch(failTest) + .then(done); + }); + + it('create plot background when react from gl3d to cartesian & back', function(done) { + Plotly.newPlot(gd, { + data: [{ type: 'scatter3d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'red' } + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe(undefined); + expect(hasBgRect()).toBe(false); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'green' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('green'); + expect(hasBgRect()).toBe(true); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter3d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'red' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe(undefined); + expect(hasBgRect()).toBe(false); + }) + .catch(failTest) + .then(done); + }); + + it('change plot background when react from cartesian to gl2d & back', function(done) { + Plotly.newPlot(gd, { + data: [{ type: 'scatter', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'yellow' } + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('yellow'); + expect(hasBgRect()).toBe(true); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter2d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'green' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('green'); + expect(hasBgRect()).toBe(true); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'yellow' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('yellow'); + expect(hasBgRect()).toBe(true); + }) + .catch(failTest) + .then(done); + }); + + it('change plot background when react from gl2d to cartesian & back', function(done) { + Plotly.newPlot(gd, { + data: [{ type: 'scatter2d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'yellow' } + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('yellow'); + expect(hasBgRect()).toBe(true); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'green' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('green'); + expect(hasBgRect()).toBe(true); + }).then(function() { + Plotly.react(gd, { + data: [{ type: 'scatter2d', x: x, y: y, z: z }], + layout: { plot_bgcolor: 'yellow' } + }); + }).then(function() { + expect(gd._fullLayout.plot_bgcolor).toBe('yellow'); + expect(hasBgRect()).toBe(true); + }) + .catch(failTest) + .then(done); + }); +}); describe('Plotly.react and uirevision attributes', function() { var gd;