Skip to content

Commit e5a71ad

Browse files
committed
Refactor clip path calculation for multi-axis shapes
1 parent d3208e9 commit e5a71ad

1 file changed

Lines changed: 44 additions & 6 deletions

File tree

src/components/shapes/draw.js

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,51 @@ function setClipPath(shapePath, gd, shapeOptions) {
196196
//
197197
// if axis is 'paper' or an axis with " domain" appended, then there is no
198198
// clip axis
199-
var clipAxes = (shapeOptions.xref + shapeOptions.yref).replace(/paper/g, '').replace(/[xyz][0-9]* *domain/g, '');
200199

201-
Drawing.setClipUrl(
202-
shapePath,
203-
clipAxes ? 'clip' + gd._fullLayout._uid + clipAxes : null,
204-
gd
205-
);
200+
var xref = shapeOptions.xref;
201+
var yref = shapeOptions.yref;
202+
203+
// For multi-axis shapes, create a custom clip path from axis bounds
204+
if(Array.isArray(xref) || Array.isArray(yref)) {
205+
var clipId = 'clip' + gd._fullLayout._uid + 'shape' + shapeOptions._index;
206+
var rect = getMultiAxisClipRect(gd, xref, yref);
207+
208+
Lib.ensureSingleById(gd._fullLayout._clips, 'clipPath', clipId, function(s) {
209+
s.append('rect');
210+
}).select('rect').attr(rect);
211+
212+
Drawing.setClipUrl(shapePath, clipId, gd);
213+
return;
214+
}
215+
216+
var clipAxes = (xref + yref).replace(/paper/g, '').replace(/[xyz][0-9]* *domain/g, '');
217+
Drawing.setClipUrl(shapePath, clipAxes ? 'clip' + gd._fullLayout._uid + clipAxes : null, gd);
218+
}
219+
220+
function getMultiAxisClipRect(gd, xref, yref) {
221+
var gs = gd._fullLayout._size;
222+
223+
function getBounds(refs, isVertical) {
224+
// Retrieve all existing axes from the references
225+
var axes = (Array.isArray(refs) ? refs : [refs])
226+
.map(r => Axes.getFromId(gd, r))
227+
.filter(Boolean);
228+
229+
// If no valid axes, return the bounds of the larger plot area
230+
if(!axes.length) {
231+
return isVertical ? [gs.t, gs.t + gs.h] : [gs.l, gs.l + gs.w];
232+
}
233+
234+
// Otherwise, we find all find and return the smallest start point
235+
// and largest end point to be used as the clip bounds
236+
var startBounds = axes.map(function(ax) { return ax._offset; });
237+
var endBounds = axes.map(function(ax) { return ax._offset + ax._length; });
238+
return [Math.min(...startBounds), Math.max(...endBounds)];
239+
}
240+
241+
var xb = getBounds(xref, false);
242+
var yb = getBounds(yref, true);
243+
return {x: xb[0], y: yb[0], width: xb[1] - xb[0], height: yb[1] - yb[0]};
206244
}
207245

208246
function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHelpers) {

0 commit comments

Comments
 (0)