Skip to content

Commit e54fbac

Browse files
ryan-williamsclaude
andcommitted
fix: preserve z-indexed subplots during relayout for correct pan/zoom
When traces have different `zorder` values, plotly.js creates z-indexed subplots (e.g., `xyz2`, `xyz3`) in `drawFramework`. However, when `relayout` is called (e.g., during resize), `supplyDefaults` resets `_plots` via `linkSubplots`, losing these z-indexed subplots. Since `relayout` doesn't trigger `drawFramework`, they aren't recreated. This caused pan/zoom to fail on the first attempt in react-plotly.js, because `updateSubplots` in `dragbox.js` couldn't find the z-indexed subplots to transform. Fix: 1. In `linkSubplots`, preserve z-indexed subplots from `oldSubplots` 2. In `updateSubplots`, include z-indexed subplots from `_plots` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent f07f1c7 commit e54fbac

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

src/plots/cartesian/dragbox.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -872,9 +872,18 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) {
872872
function updateSubplots(viewBox) {
873873
var fullLayout = gd._fullLayout;
874874
var plotinfos = fullLayout._plots;
875-
var subplots = fullLayout._subplots.cartesian;
875+
var subplots = fullLayout._subplots.cartesian.slice();
876876
var i, sp, xa, ya;
877877

878+
// Include z-indexed subplots from _plots that may not be in _subplots.cartesian
879+
// (e.g., after a relayout that resets _subplots.cartesian but preserves _plots)
880+
var zindexSeparator = constants.zindexSeparator;
881+
for(var plotId in plotinfos) {
882+
if(plotId.indexOf(zindexSeparator) !== -1 && subplots.indexOf(plotId) === -1) {
883+
subplots.push(plotId);
884+
}
885+
}
886+
878887
if(hasSplom) {
879888
Registry.subplotsRegistry.splom.drag(gd);
880889
}

src/plots/plots.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ var Color = require('../components/color');
1414
var BADNUM = require('../constants/numerical').BADNUM;
1515

1616
var axisIDs = require('./cartesian/axis_ids');
17+
var cartesianConstants = require('./cartesian/constants');
1718
var clearOutline = require('../components/shapes/handle_outline').clearOutline;
1819
var scatterAttrs = require('../traces/scatter/layout_attributes');
1920

@@ -895,6 +896,19 @@ plots.linkSubplots = function(newFullData, newFullLayout, oldFullData, oldFullLa
895896
}
896897
}
897898

899+
// Preserve z-indexed subplots (e.g. 'xyz2', 'xyz3') from oldSubplots to _plots only.
900+
// These are created by drawFramework when traces have different zorder values.
901+
// We preserve them to _plots (not _subplots.cartesian) so that drag/pan operations
902+
// in dragbox.js can still transform them during relayout operations that don't
903+
// trigger a full redraw (e.g., resize). If drawFramework runs later, it will
904+
// properly update/remove these subplots as needed.
905+
var zindexSeparator = cartesianConstants.zindexSeparator;
906+
for(var oldId in oldSubplots) {
907+
if(oldId.indexOf(zindexSeparator) !== -1 && !newSubplots[oldId]) {
908+
newSubplots[oldId] = oldSubplots[oldId];
909+
}
910+
}
911+
898912
// while we're at it, link overlaying axes to their main axes and
899913
// anchored axes to the axes they're anchored to
900914
var axList = axisIDs.list(mockGd, null, true);

0 commit comments

Comments
 (0)