Skip to content

Commit 6c6b21f

Browse files
committed
Apply zorder to traces on overlaying axes
1 parent dca16b5 commit 6c6b21f

File tree

2 files changed

+79
-66
lines changed

2 files changed

+79
-66
lines changed

src/plots/cartesian/index.js

+72-50
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ exports.finalizeSubplots = function(layoutIn, layoutOut) {
127127
exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
128128
var fullLayout = gd._fullLayout;
129129
var calcdata = gd.calcdata;
130-
var i;
130+
var i, j;
131131

132132
// Traces is a list of trace indices to (re)plot. If it's not provided,
133133
// then it's a complete replot so we create a new list and add all trace indices
@@ -142,41 +142,65 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
142142

143143
var trace;
144144
var subplot;
145-
var subplotZindexGroups = {};
145+
var subplotZorderGroups = {};
146146
for(var t = 0; t < calcdata.length; t++) {
147147
trace = calcdata[t][0].trace;
148-
var zi = trace.zindex || 0;
148+
var zi = trace.zorder || 0;
149149
subplot = trace.xaxis + trace.yaxis;
150-
if(!subplotZindexGroups[zi]) subplotZindexGroups[zi] = {};
151-
if(!subplotZindexGroups[zi][subplot]) subplotZindexGroups[zi][subplot] = [];
152-
subplotZindexGroups[zi][subplot].push(calcdata[t]);
150+
if(!subplotZorderGroups[zi]) subplotZorderGroups[zi] = {};
151+
if(!subplotZorderGroups[zi][subplot]) subplotZorderGroups[zi][subplot] = [];
152+
subplotZorderGroups[zi][subplot].push(calcdata[t]);
153153
}
154-
var zindices = Object.keys(subplotZindexGroups)
154+
var zindices = Object.keys(subplotZorderGroups)
155155
.map(Number)
156156
.sort(Lib.sorterAsc);
157157

158+
var prevSubplots = [];
158159
var subplots;
160+
var zin;
161+
var subplotId;
162+
var newsubplotZorderGroups = {};
163+
for(i = 0; i < zindices.length; i++) {
164+
zin = zindices[i];
165+
subplots = Object.keys(subplotZorderGroups[zin]);
166+
167+
// For each subplot
168+
for(j = 0; j < subplots.length; j++) {
169+
subplot = subplots[j];
170+
if(prevSubplots.indexOf(subplot) === -1) {
171+
prevSubplots.push(subplot);
172+
subplotId = subplot;
173+
} else {
174+
subplotId = subplot + '-over-' + i;
175+
}
176+
if(!newsubplotZorderGroups[zin]) newsubplotZorderGroups[zin] = {};
177+
if(!newsubplotZorderGroups[zin][subplotId]) newsubplotZorderGroups[zin][subplotId] = [];
178+
newsubplotZorderGroups[zin][subplotId].push(subplotZorderGroups[zin][subplot]);
179+
}
180+
}
181+
159182
var zindex;
160183
var subplotLayerData = {};
161184
for(i = 0; i < zindices.length; i++) {
162185
zindex = zindices[i];
163-
subplots = Object.keys(subplotZindexGroups[zindex]);
186+
subplots = Object.keys(newsubplotZorderGroups[zindex]);
164187

165188
// For each subplot
166-
for(var j = 0; j < subplots.length; j++) {
189+
for(j = 0; j < subplots.length; j++) {
167190
subplot = subplots[j];
168191
var subplotInfo = fullLayout._plots[subplot];
169192

170193
// Get all calcdata (traces) for this subplot:
171194
var cdSubplot = [];
172195
var pcd;
173196
// For each trace
174-
for(var k = 0; k < subplotZindexGroups[zindex][subplot].length; k++) {
175-
var cd = subplotZindexGroups[zindex][subplot][k];
197+
for(var k = 0; k < newsubplotZorderGroups[zindex][subplot].length; k++) {
198+
var cd = newsubplotZorderGroups[zindex][subplot][k][0];
176199
trace = cd[0].trace;
200+
177201
// Skip trace if whitelist provided and it's not whitelisted:
178202
// if (Array.isArray(traces) && traces.indexOf(i) === -1) continue;
179-
if(trace.xaxis + trace.yaxis === subplot) {
203+
if(trace.xaxis + trace.yaxis === subplot || (subplot.indexOf('-over-') !== -1 && subplot.indexOf(trace.xaxis + trace.yaxis) === 0)) {
180204
// XXX: Should trace carpet dependencies. Only replot all carpet plots if the carpet
181205
// axis has actually changed:
182206
//
@@ -240,8 +264,7 @@ function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback
240264

241265
if(categories.svg) {
242266
var classBaseName = (_module.layerName || name + 'layer');
243-
//var className = classBaseName + (z ? Number(z) + 1 : '');
244-
var className = classBaseName + '_' + zorder;
267+
var className = classBaseName + (z ? Number(z) + 1 : '');
245268
var plotMethod = _module.plot;
246269

247270
// plot all visible traces of this type on this subplot at once
@@ -254,7 +277,7 @@ function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback
254277
if(cdModule.length) {
255278
layerData.push({
256279
i: traceLayerClasses.indexOf(classBaseName),
257-
zorder: zorder,
280+
zorder: z,
258281
className: className,
259282
plotMethod: plotMethod,
260283
cdModule: cdModule
@@ -397,7 +420,7 @@ exports.drawFramework = function(gd) {
397420

398421
var subplotLayers = fullLayout._cartesianlayer.selectAll('.subplot')
399422
.data(subplotData, String);
400-
423+
401424
subplotLayers.enter().append('g')
402425
.attr('class', function(d) { return 'subplot ' + d[0]; });
403426

@@ -411,7 +434,7 @@ exports.drawFramework = function(gd) {
411434
var plotinfo = fullLayout._plots[id];
412435

413436
plotinfo.plotgroup = d3.select(this);
414-
makeSubplotLayer(gd, plotinfo);
437+
makeSubplotLayer(gd, plotinfo, id);
415438

416439
// make separate drag layers for each subplot,
417440
// but append them to paper rather than the plot groups,
@@ -421,15 +444,15 @@ exports.drawFramework = function(gd) {
421444
};
422445

423446
exports.rangePlot = function(gd, plotinfo, cdSubplot) {
424-
makeSubplotLayer(gd, plotinfo);
447+
makeSubplotLayer(gd, plotinfo, plotinfo.id);
425448
plotOne(gd, plotinfo, cdSubplot);
426449
Plots.style(gd);
427450
};
428451

429452
function makeSubplotData(gd) {
430453
var fullLayout = gd._fullLayout;
431454
var ids = fullLayout._subplots.cartesian;
432-
455+
433456
var i, j, id, plotinfo, xa, ya;
434457

435458
// split 'regular' and 'overlaying' subplots
@@ -440,35 +463,37 @@ function makeSubplotData(gd) {
440463

441464
var trace;
442465
var subplot;
443-
var subplotZindexGroups = {};
466+
var subplotZorderGroups = {};
444467
for(var t = 0; t < calcdata.length; t++) {
445468
trace = calcdata[t][0].trace;
446-
var zi = trace.zindex || 0;
469+
var zi = trace.zorder || 0;
447470
subplot = trace.xaxis + trace.yaxis;
448-
if(!subplotZindexGroups[zi]) subplotZindexGroups[zi] = {};
449-
if(!subplotZindexGroups[zi][subplot]) subplotZindexGroups[zi][subplot] = [];
450-
subplotZindexGroups[zi][subplot].push(calcdata[t]);
471+
if(!subplotZorderGroups[zi]) subplotZorderGroups[zi] = {};
472+
if(!subplotZorderGroups[zi][subplot]) subplotZorderGroups[zi][subplot] = [];
473+
subplotZorderGroups[zi][subplot].push(calcdata[t]);
451474
}
452-
var zindices = Object.keys(subplotZindexGroups)
475+
var zindices = Object.keys(subplotZorderGroups)
453476
.map(Number)
454477
.sort(Lib.sorterAsc);
455478
var len = zindices.length;
456479

480+
var mainplot;
481+
var mainplotinfo;
457482
for(i = 0; i < len; i++) {
458-
var zindex = subplotZindexGroups[zindices[i]];
459-
var ids = Object.keys(zindex);
460-
for(var j=0; j<ids.length; j++) {
461-
var id = ids[j];
483+
var zindex = subplotZorderGroups[zindices[i]];
484+
ids = Object.keys(zindex);
485+
for(j = 0; j < ids.length; j++) {
486+
id = ids[j];
462487
plotinfo = fullLayout._plots[id];
463488

464-
var mainplot = mainplot ? mainplot : id;
465-
var mainplotinfo = Object.assign({}, fullLayout._plots[mainplot])
489+
mainplot = mainplot ? mainplot : id;
490+
mainplotinfo = fullLayout._plots[mainplot];
466491
plotinfo.overlays = [];
467492

468-
if (regulars.indexOf(id) !== -1 || overlays.indexOf(id) !== -1 ){
493+
if(regulars.indexOf(id) !== -1 || overlays.indexOf(id) !== -1) {
469494
plotinfo.mainplot = mainplot;
470495
plotinfo.mainplotinfo = mainplotinfo;
471-
overlays.push(id+'-over-'+i);
496+
overlays.push(id + '-over-' + i);
472497
} else if(mainplot !== id && mainplotinfo) {
473498
plotinfo.mainplot = mainplot;
474499
plotinfo.mainplotinfo = mainplotinfo;
@@ -484,8 +509,8 @@ function makeSubplotData(gd) {
484509
// fill in list of overlaying subplots in 'main plot'
485510
for(i = 0; i < overlays.length; i++) {
486511
id = overlays[i];
487-
if (id.indexOf('-over-')!==-1) {
488-
id = id.split("-over-")[0];
512+
if(id.indexOf('-over-') !== -1) {
513+
id = id.split('-over-')[0];
489514
}
490515
var plotinfoCopy = Object.assign({}, fullLayout._plots[id]);
491516
plotinfoCopy.id = overlays[i];
@@ -497,34 +522,33 @@ function makeSubplotData(gd) {
497522
var subplotData = new Array(subplotIds.length);
498523
for(i = 0; i < subplotIds.length; i++) {
499524
id = subplotIds[i];
500-
if (id.indexOf('-over-')!==-1) {
501-
fullLayout._plots[id] = Object.assign({}, fullLayout._plots[id.split("-over-")[0]]);
525+
if(id.indexOf('-over-') !== -1) {
526+
fullLayout._plots[id] = Object.assign({}, fullLayout._plots[id.split('-over-')[0]]);
502527
}
503528
plotinfo = fullLayout._plots[id];
504529
xa = plotinfo.xaxis;
505530
ya = plotinfo.yaxis;
506531

507532
// use info about axis layer and overlaying pattern
508533
// to clean what need to be cleaned up in exit selection
509-
var d = [id, xa.layer, ya.layer, xa.overlaying || '' , ya.overlaying || ''];
510-
if (id.indexOf('-over-')!==-1){
534+
var d = [id, xa.layer, ya.layer, xa.overlaying || '', ya.overlaying || ''];
535+
if(id.indexOf('-over-') !== -1) {
511536
for(j = 0; j < plotinfo.overlays.length; j++) {
512537
d.push(plotinfo.overlays[j].id);
513538
}
514-
}
539+
}
515540
subplotData[i] = d;
516541
}
517542
return subplotData;
518543
}
519544

520-
function makeSubplotLayer(gd, plotinfo) {
545+
function makeSubplotLayer(gd, plotinfo, id) {
521546
var plotgroup = plotinfo.plotgroup;
522-
var id = plotinfo.id;
523547
var xLayer = constants.layerValue2layerClass[plotinfo.xaxis.layer];
524548
var yLayer = constants.layerValue2layerClass[plotinfo.yaxis.layer];
525549
var hasOnlyLargeSploms = gd._fullLayout._hasOnlyLargeSploms;
526550

527-
if(!plotinfo.mainplot || id.indexOf('-over-') === -1) {
551+
if(!plotinfo.mainplot || (plotinfo.mainplot === id && id.indexOf('-over-') === -1)) {
528552
if(hasOnlyLargeSploms) {
529553
// TODO could do even better
530554
// - we don't need plot (but we would have to mock it in lsInner
@@ -590,7 +614,7 @@ function makeSubplotLayer(gd, plotinfo) {
590614

591615
ensureSingle(mainplotinfo.overlinesBelow, 'path', xId);
592616
ensureSingle(mainplotinfo.overlinesBelow, 'path', yId);
593-
617+
594618
ensureSingle(mainplotinfo.overaxesBelow, 'g', xId);
595619
ensureSingle(mainplotinfo.overaxesBelow, 'g', yId);
596620

@@ -601,7 +625,6 @@ function makeSubplotLayer(gd, plotinfo) {
601625

602626
ensureSingle(mainplotinfo.overaxesAbove, 'g', xId);
603627
ensureSingle(mainplotinfo.overaxesAbove, 'g', yId);
604-
605628

606629
// set refs to correct layers as determined by 'abovetraces'
607630
plotinfo.xlines = mainplotgroup.select('.overlines-' + xLayer).select('.' + xId);
@@ -613,15 +636,14 @@ function makeSubplotLayer(gd, plotinfo) {
613636
// common attributes for all subplots, overlays or not
614637

615638
if(!hasOnlyLargeSploms) {
616-
if (plotinfo.minorGridlayer){
639+
if(plotinfo.minorGridlayer) {
617640
ensureSingleAndAddDatum(plotinfo.minorGridlayer, 'g', plotinfo.xaxis._id);
618-
ensureSingleAndAddDatum(plotinfo.minorGridlayer, 'g', plotinfo.yaxis._id);
619-
plotinfo.minorGridlayer.selectAll('g')
641+
ensureSingleAndAddDatum(plotinfo.minorGridlayer, 'g', plotinfo.yaxis._id);
642+
plotinfo.minorGridlayer.selectAll('g')
620643
.map(function(d) { return d[0]; })
621644
.sort(axisIds.idSort);
622-
623645
}
624-
if (plotinfo.gridlayer){
646+
if(plotinfo.gridlayer) {
625647
ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.xaxis._id);
626648
ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.yaxis._id);
627649
plotinfo.gridlayer.selectAll('g')

test/image/mocks/zorder_mult_axes.json

+7-16
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,40 @@
33
{
44
"x": [2, 3, 4, 5],
55
"y": [4, 3, 9, 5],
6-
"name": "blue",
6+
"name": "xy - zorder 10",
77
"type": "scatter",
88
"marker": {"size": 20},
99
"line": {"width": 6},
1010
"yaxis": "y",
11-
"xaxis": "x",
1211
"zorder": 10
1312
},
1413
{
1514
"x": [2, 3, 4, 5, 6],
1615
"y": [2, 5, 4, 6, 4],
17-
"name": "orange",
16+
"name": "xy - zorder 0",
1817
"type": "scatter",
1918
"marker": {"size": 20},
2019
"line": {"width": 6},
21-
"yaxis": "y2",
22-
"xaxis": "x2",
23-
"zorder": 5
20+
"zorder": 0
2421
},
2522
{
2623
"x": [3, 4, 5, 6, 7],
2724
"y": [1, 8, 6, 8, 5],
28-
"name": "green",
25+
"name": "xy2 - zorder 5",
2926
"type": "scatter",
3027
"marker": {"size": 20},
3128
"line": {"width": 6},
3229
"yaxis": "y2",
33-
"xaxis": "x",
34-
"zorder": 7
30+
"zorder": 5
3531
},
3632

3733
{
3834
"x": [2, 3, 4, 5, 6, 7],
3935
"y": [4, 2, 6, 1, 6, 9],
40-
"name": "bar",
36+
"name": "xy2 - zorder 6",
4137
"type": "bar",
4238
"yaxis": "y2",
43-
"xaxis": "x2",
44-
"zorder": 8
39+
"zorder": 6
4540
}
4641
],
4742
"layout": {
@@ -50,10 +45,6 @@
5045
"title": {
5146
"text": "zorder stacking"
5247
}
53-
, "overlaying": "x2"
54-
},
55-
"x2axis": {
56-
"title":{"text":"x2"}
5748
},
5849
"yaxis": {
5950
"side": "right",

0 commit comments

Comments
 (0)