Skip to content

Commit bbb31f4

Browse files
authored
Merge pull request #1871 from plotly/axis-layer-above-below
Implement `axis.layer` with 'above traces' and 'below traces' values
2 parents 0496144 + 6f494c6 commit bbb31f4

25 files changed

+343
-108
lines changed

devtools/test_dashboard/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
<script type="text/javascript" src="../../dist/extras/mathjax/MathJax.js?config=TeX-AMS-MML_SVG"></script>
2323
<script id="source" type="text/javascript" src="../../build/plotly.js"></script>
24-
<script type="text/javascript" src="../../test/image/strict-d3.js" charset="utf-8"></script>
2524
<script type="text/javascript" src="../../build/test_dashboard-bundle.js"></script>
2625
</body>
2726
</html>

src/plot_api/subroutines.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ exports.lsInner = function(gd) {
180180

181181
Drawing.setClipUrl(plotinfo.plot, plotClipId);
182182

183-
for(i = 0; i < cartesianConstants.layers.length; i++) {
184-
var layer = cartesianConstants.layers[i];
183+
for(i = 0; i < cartesianConstants.traceLayerClasses.length; i++) {
184+
var layer = cartesianConstants.traceLayerClasses[i];
185185
if(layer !== 'scatterlayer') {
186186
plotinfo.plot.selectAll('g.' + layer).call(Drawing.setClipUrl, layerClipId);
187187
}

src/plots/cartesian/constants.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,24 @@ module.exports = {
5151
DFLTRANGEX: [-1, 6],
5252
DFLTRANGEY: [-1, 4],
5353

54-
// Layers to keep plot types in the right order.
54+
// Layers to keep trace types in the right order.
5555
// from back to front:
5656
// 1. heatmaps, 2D histos and contour maps
5757
// 2. bars / 1D histos
5858
// 3. errorbars for bars and scatter
5959
// 4. scatter
6060
// 5. box plots
61-
layers: [
61+
traceLayerClasses: [
6262
'imagelayer',
6363
'maplayer',
6464
'barlayer',
6565
'carpetlayer',
6666
'boxlayer',
6767
'scatterlayer'
68-
]
68+
],
69+
70+
layerValue2layerClass: {
71+
'above traces': 'above',
72+
'below traces': 'below'
73+
}
6974
};

src/plots/cartesian/dragbox.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
743743
var plotDx = xa2._offset - clipDx / xScaleFactor2,
744744
plotDy = ya2._offset - clipDy / yScaleFactor2;
745745

746-
fullLayout._defs.selectAll('#' + subplot.clipId)
746+
fullLayout._defs.select('#' + subplot.clipId + '> rect')
747747
.call(Drawing.setTranslate, clipDx, clipDy)
748748
.call(Drawing.setScale, xScaleFactor2, yScaleFactor2);
749749

src/plots/cartesian/index.js

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,8 @@ function makeSubplotData(gd) {
296296
function makeSubplotLayer(plotinfo) {
297297
var plotgroup = plotinfo.plotgroup;
298298
var id = plotinfo.id;
299+
var xLayer = constants.layerValue2layerClass[plotinfo.xaxis.layer];
300+
var yLayer = constants.layerValue2layerClass[plotinfo.yaxis.layer];
299301

300302
if(!plotinfo.mainplot) {
301303
var backLayer = joinLayer(plotgroup, 'g', 'layer-subplot');
@@ -308,19 +310,36 @@ function makeSubplotLayer(plotinfo) {
308310
plotinfo.zerolinelayer = joinLayer(plotgroup, 'g', 'zerolinelayer');
309311
plotinfo.overzero = joinLayer(plotgroup, 'g', 'overzero');
310312

313+
joinLayer(plotgroup, 'path', 'xlines-below');
314+
joinLayer(plotgroup, 'path', 'ylines-below');
315+
plotinfo.overlinesBelow = joinLayer(plotgroup, 'g', 'overlines-below');
316+
317+
joinLayer(plotgroup, 'g', 'xaxislayer-below');
318+
joinLayer(plotgroup, 'g', 'yaxislayer-below');
319+
plotinfo.overaxesBelow = joinLayer(plotgroup, 'g', 'overaxes-below');
320+
311321
plotinfo.plot = joinLayer(plotgroup, 'g', 'plot');
312322
plotinfo.overplot = joinLayer(plotgroup, 'g', 'overplot');
313323

314-
plotinfo.xlines = joinLayer(plotgroup, 'path', 'xlines');
315-
plotinfo.ylines = joinLayer(plotgroup, 'path', 'ylines');
316-
plotinfo.overlines = joinLayer(plotgroup, 'g', 'overlines');
324+
joinLayer(plotgroup, 'path', 'xlines-above');
325+
joinLayer(plotgroup, 'path', 'ylines-above');
326+
plotinfo.overlinesAbove = joinLayer(plotgroup, 'g', 'overlines-above');
327+
328+
joinLayer(plotgroup, 'g', 'xaxislayer-above');
329+
joinLayer(plotgroup, 'g', 'yaxislayer-above');
330+
plotinfo.overaxesAbove = joinLayer(plotgroup, 'g', 'overaxes-above');
317331

318-
plotinfo.xaxislayer = joinLayer(plotgroup, 'g', 'xaxislayer');
319-
plotinfo.yaxislayer = joinLayer(plotgroup, 'g', 'yaxislayer');
320-
plotinfo.overaxes = joinLayer(plotgroup, 'g', 'overaxes');
332+
// set refs to correct layers as determined by 'axis.layer'
333+
plotinfo.xlines = plotgroup.select('.xlines-' + xLayer);
334+
plotinfo.ylines = plotgroup.select('.ylines-' + yLayer);
335+
plotinfo.xaxislayer = plotgroup.select('.xaxislayer-' + xLayer);
336+
plotinfo.yaxislayer = plotgroup.select('.yaxislayer-' + yLayer);
321337
}
322338
else {
323339
var mainplotinfo = plotinfo.mainplotinfo;
340+
var mainplotgroup = mainplotinfo.plotgroup;
341+
var xId = id + '-x';
342+
var yId = id + '-y';
324343

325344
// now make the components of overlaid subplots
326345
// overlays don't have backgrounds, and append all
@@ -330,17 +349,29 @@ function makeSubplotLayer(plotinfo) {
330349
plotinfo.gridlayer = joinLayer(mainplotinfo.overgrid, 'g', id);
331350
plotinfo.zerolinelayer = joinLayer(mainplotinfo.overzero, 'g', id);
332351

352+
joinLayer(mainplotinfo.overlinesBelow, 'path', xId);
353+
joinLayer(mainplotinfo.overlinesBelow, 'path', yId);
354+
joinLayer(mainplotinfo.overaxesBelow, 'g', xId);
355+
joinLayer(mainplotinfo.overaxesBelow, 'g', yId);
356+
333357
plotinfo.plot = joinLayer(mainplotinfo.overplot, 'g', id);
334-
plotinfo.xlines = joinLayer(mainplotinfo.overlines, 'path', id + '-x');
335-
plotinfo.ylines = joinLayer(mainplotinfo.overlines, 'path', id + '-y');
336-
plotinfo.xaxislayer = joinLayer(mainplotinfo.overaxes, 'g', id + '-x');
337-
plotinfo.yaxislayer = joinLayer(mainplotinfo.overaxes, 'g', id + '-y');
358+
359+
joinLayer(mainplotinfo.overlinesAbove, 'path', xId);
360+
joinLayer(mainplotinfo.overlinesAbove, 'path', yId);
361+
joinLayer(mainplotinfo.overaxesAbove, 'g', xId);
362+
joinLayer(mainplotinfo.overaxesAbove, 'g', yId);
363+
364+
// set refs to correct layers as determined by 'abovetraces'
365+
plotinfo.xlines = mainplotgroup.select('.overlines-' + xLayer).select('.' + xId);
366+
plotinfo.ylines = mainplotgroup.select('.overlines-' + yLayer).select('.' + yId);
367+
plotinfo.xaxislayer = mainplotgroup.select('.overaxes-' + xLayer).select('.' + xId);
368+
plotinfo.yaxislayer = mainplotgroup.select('.overaxes-' + yLayer).select('.' + yId);
338369
}
339370

340371
// common attributes for all subplots, overlays or not
341372

342-
for(var i = 0; i < constants.layers.length; i++) {
343-
joinLayer(plotinfo.plot, 'g', constants.layers[i]);
373+
for(var i = 0; i < constants.traceLayerClasses.length; i++) {
374+
joinLayer(plotinfo.plot, 'g', constants.traceLayerClasses[i]);
344375
}
345376

346377
plotinfo.xlines

src/plots/cartesian/layout_attributes.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,20 @@ module.exports = {
573573
'If *false*, this axis does not overlay any same-letter axes.'
574574
].join(' ')
575575
},
576+
layer: {
577+
valType: 'enumerated',
578+
values: ['above traces', 'below traces'],
579+
dflt: 'above traces',
580+
role: 'info',
581+
description: [
582+
'Sets the layer on which this axis is displayed.',
583+
'If *above traces*, this axis is displayed above all the subplot\'s traces',
584+
'If *below traces*, this axis is displayed below all the subplot\'s traces,',
585+
'but above the grid lines.',
586+
'Useful when used together with scatter-like traces with `cliponaxis`',
587+
'set to *false* to show markers and/or text nodes above this axis.'
588+
].join(' ')
589+
},
576590
domain: {
577591
valType: 'info_array',
578592
role: 'info',

src/plots/cartesian/position_defaults.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,7 @@ module.exports = function handlePositionDefaults(containerIn, containerOut, coer
5959
Lib.noneOrAll(containerIn.domain, containerOut.domain, [0, 1]);
6060
}
6161

62+
coerce('layer');
63+
6264
return containerOut;
6365
};

src/plots/cartesian/transition_axes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
137137
var xa2 = subplot.xaxis;
138138
var ya2 = subplot.yaxis;
139139

140-
fullLayout._defs.selectAll('#' + subplot.clipId)
140+
fullLayout._defs.select('#' + subplot.clipId + '> rect')
141141
.call(Drawing.setTranslate, 0, 0)
142142
.call(Drawing.setScale, 1, 1);
143143

@@ -221,7 +221,7 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
221221
var plotDx = xa2._offset - fracDx,
222222
plotDy = ya2._offset - fracDy;
223223

224-
fullLayout._defs.selectAll('#' + subplot.clipId)
224+
fullLayout._defs.select('#' + subplot.clipId + '> rect')
225225
.call(Drawing.setTranslate, clipDx, clipDy)
226226
.call(Drawing.setScale, 1 / xScaleFactor, 1 / yScaleFactor);
227227

src/plots/plots.js

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -638,24 +638,35 @@ plots.linkSubplots = function(newFullData, newFullLayout, oldFullData, oldFullLa
638638
var ids = Plotly.Axes.getSubplots(mockGd);
639639

640640
for(var i = 0; i < ids.length; i++) {
641-
var id = ids[i],
642-
oldSubplot = oldSubplots[id],
643-
plotinfo;
641+
var id = ids[i];
642+
var oldSubplot = oldSubplots[id];
643+
var xaxis = Plotly.Axes.getFromId(mockGd, id, 'x');
644+
var yaxis = Plotly.Axes.getFromId(mockGd, id, 'y');
645+
var plotinfo;
644646

645647
if(oldSubplot) {
646648
plotinfo = newSubplots[id] = oldSubplot;
647649

648650
if(plotinfo._scene2d) {
649651
plotinfo._scene2d.updateRefs(newFullLayout);
650652
}
651-
}
652-
else {
653+
654+
if(plotinfo.xaxis.layer !== xaxis.layer) {
655+
plotinfo.xlines.attr('d', null);
656+
plotinfo.xaxislayer.selectAll('*').remove();
657+
}
658+
659+
if(plotinfo.yaxis.layer !== yaxis.layer) {
660+
plotinfo.ylines.attr('d', null);
661+
plotinfo.yaxislayer.selectAll('*').remove();
662+
}
663+
} else {
653664
plotinfo = newSubplots[id] = {};
654665
plotinfo.id = id;
655666
}
656667

657-
plotinfo.xaxis = Plotly.Axes.getFromId(mockGd, id, 'x');
658-
plotinfo.yaxis = Plotly.Axes.getFromId(mockGd, id, 'y');
668+
plotinfo.xaxis = xaxis;
669+
plotinfo.yaxis = yaxis;
659670

660671
// By default, we clip at the subplot level,
661672
// but if one trace on a given subplot has *cliponaxis* set to false,

src/plots/ternary/ternary.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ proto.adjustLayout = function(ternaryLayout, graphSize) {
292292
_this.plotContainer.selectAll('.scatterlayer,.maplayer')
293293
.attr('transform', plotTransform);
294294

295-
_this.clipDefRelative.attr('transform', null);
295+
_this.clipDefRelative.select('path').attr('transform', null);
296296

297297
// TODO: shift axes to accommodate linewidth*sin(30) tick mark angle
298298

@@ -619,7 +619,7 @@ proto.initInteractions = function() {
619619
.attr('transform', plotTransform);
620620

621621
var plotTransform2 = 'translate(' + -dx + ',' + -dy + ')';
622-
_this.clipDefRelative.attr('transform', plotTransform2);
622+
_this.clipDefRelative.select('path').attr('transform', plotTransform2);
623623

624624
// move the ticks
625625
_this.aaxis.range = [mins.a, _this.sum - mins.b - mins.c];

0 commit comments

Comments
 (0)