Skip to content

Commit df9361c

Browse files
committed
zindex first pass. scatter and bar traces only
1 parent 39bd75f commit df9361c

File tree

8 files changed

+129
-35
lines changed

8 files changed

+129
-35
lines changed

src/plots/cartesian/index.js

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -130,21 +130,27 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
130130
var calcdata = gd.calcdata;
131131
var i;
132132

133+
// Traces is a list of trace indices to (re)plot. If it's not provided,
134+
// then it's a complete replot so we create a new list and add all trace indices
135+
// which are in calcdata.
136+
133137
if(!Array.isArray(traces)) {
134138
// If traces is not provided, then it's a complete replot and missing
135139
// traces are removed
136140
traces = [];
137141
for(i = 0; i < calcdata.length; i++) traces.push(i);
138142
}
139143

144+
// For each subplot
140145
for(i = 0; i < subplots.length; i++) {
141146
var subplot = subplots[i];
142147
var subplotInfo = fullLayout._plots[subplot];
143148

144-
// Get all calcdata for this subplot:
149+
// Get all calcdata (traces) for this subplot:
145150
var cdSubplot = [];
146151
var pcd;
147152

153+
// For each trace
148154
for(var j = 0; j < calcdata.length; j++) {
149155
var cd = calcdata[j];
150156
var trace = cd[0].trace;
@@ -178,7 +184,7 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
178184
pcd = cd;
179185
}
180186
}
181-
187+
// Plot the traces for this subplot
182188
plotOne(gd, subplotInfo, cdSubplot, transitionOpts, makeOnCompleteCallback);
183189
}
184190
};
@@ -189,41 +195,60 @@ function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback
189195
var modules = fullLayout._modules;
190196
var _module, cdModuleAndOthers, cdModule;
191197

198+
// Separate traces by zindex and plot each zindex group separately
199+
// TODO: Performance
200+
var traceZindexGroups = {};
201+
for(var t = 0; t < cdSubplot.length; t++) {
202+
var trace = cdSubplot[t][0].trace;
203+
var zi = trace.zindex || 0;
204+
if(!traceZindexGroups[zi]) traceZindexGroups[zi] = [];
205+
traceZindexGroups[zi].push(cdSubplot[t]);
206+
}
207+
192208
var layerData = [];
193209
var zoomScaleQueryParts = [];
194210

195-
for(var i = 0; i < modules.length; i++) {
196-
_module = modules[i];
197-
var name = _module.name;
198-
var categories = Registry.modules[name].categories;
199-
200-
if(categories.svg) {
201-
var className = (_module.layerName || name + 'layer');
202-
var plotMethod = _module.plot;
203-
204-
// plot all visible traces of this type on this subplot at once
205-
cdModuleAndOthers = getModuleCalcData(cdSubplot, plotMethod);
206-
cdModule = cdModuleAndOthers[0];
207-
// don't need to search the found traces again - in fact we need to NOT
208-
// so that if two modules share the same plotter we don't double-plot
209-
cdSubplot = cdModuleAndOthers[1];
210-
211-
if(cdModule.length) {
212-
layerData.push({
213-
i: traceLayerClasses.indexOf(className),
214-
className: className,
215-
plotMethod: plotMethod,
216-
cdModule: cdModule
217-
});
218-
}
211+
// Plot each zindex group in ascending order
212+
var zindices = Object.keys(traceZindexGroups)
213+
.map(Number)
214+
.sort(function(a, b) { return a - b; });
215+
for(var z = 0; z < zindices.length; z++) {
216+
var zindex = zindices[z];
217+
// For each "module" (trace type)
218+
for(var i = 0; i < modules.length; i++) {
219+
_module = modules[i];
220+
var name = _module.name;
221+
var categories = Registry.modules[name].categories;
222+
223+
if(categories.svg) {
224+
var className = (_module.layerName || name + 'layer') + (zindex ? '-' + z : '');
225+
var plotMethod = _module.plot;
226+
227+
// plot all visible traces of this type on this subplot at once
228+
cdModuleAndOthers = getModuleCalcData(cdSubplot, plotMethod, zindex);
229+
cdModule = cdModuleAndOthers[0];
230+
// don't need to search the found traces again - in fact we need to NOT
231+
// so that if two modules share the same plotter we don't double-plot
232+
cdSubplot = cdModuleAndOthers[1];
233+
234+
if(cdModule.length) {
235+
layerData.push({
236+
i: traceLayerClasses.indexOf(className),
237+
z: z,
238+
className: className,
239+
plotMethod: plotMethod,
240+
cdModule: cdModule
241+
});
242+
}
219243

220-
if(categories.zoomScale) {
221-
zoomScaleQueryParts.push('.' + className);
244+
if(categories.zoomScale) {
245+
zoomScaleQueryParts.push('.' + className);
246+
}
222247
}
223248
}
224249
}
225-
226-
layerData.sort(function(a, b) { return a.i - b.i; });
250+
// Sort the layers primarily by z, then by i
251+
layerData.sort(function(a, b) { return a.z - b.z || a.i - b.i; });
227252

228253
var layers = plotinfo.plot.selectAll('g.mlayer')
229254
.data(layerData, function(d) { return d.className; });
@@ -434,7 +459,6 @@ function makeSubplotData(gd) {
434459
}
435460
subplotData[i] = d;
436461
}
437-
438462
return subplotData;
439463
}
440464

src/plots/get_data.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ exports.getSubplotCalcData = function(calcData, type, subplotId) {
3939
* @param {array} calcdata: as in gd.calcdata
4040
* @param {object|string|fn} arg1:
4141
* the plotting module, or its name, or its plot method
42-
*
42+
* @param {int} arg2: (optional) zindex to filter on
4343
* @return {array[array]} [foundCalcdata, remainingCalcdata]
4444
*/
45-
exports.getModuleCalcData = function(calcdata, arg1) {
45+
exports.getModuleCalcData = function(calcdata, arg1, arg2) {
4646
var moduleCalcData = [];
4747
var remainingCalcData = [];
4848

@@ -57,6 +57,8 @@ exports.getModuleCalcData = function(calcdata, arg1) {
5757
if(!plotMethod) {
5858
return [moduleCalcData, calcdata];
5959
}
60+
var zindex = arg2;
61+
var filterByZ = (zindex !== undefined);
6062

6163
for(var i = 0; i < calcdata.length; i++) {
6264
var cd = calcdata[i];
@@ -70,7 +72,7 @@ exports.getModuleCalcData = function(calcdata, arg1) {
7072
// would suggest), but by 'module plot method' so that if some traces
7173
// share the same module plot method (e.g. bar and histogram), we
7274
// only call it one!
73-
if(trace._module && trace._module.plot === plotMethod) {
75+
if(trace._module && trace._module.plot === plotMethod && (!filterByZ || trace.zindex === zindex)) {
7476
moduleCalcData.push(cd);
7577
} else {
7678
remainingCalcData.push(cd);

src/traces/bar/attributes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ module.exports = {
226226
textfont: scatterAttrs.unselected.textfont,
227227
editType: 'style'
228228
},
229+
zindex: scatterAttrs.zindex,
229230

230231
_deprecated: {
231232
bardir: {

src/traces/bar/defaults.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
2929
coerce('xhoverformat');
3030
coerce('yhoverformat');
3131

32+
coerce('zindex');
33+
3234
coerce('orientation', (traceOut.x && !traceOut.y) ? 'h' : 'v');
3335
coerce('base');
3436
coerce('offset');

src/traces/bar/style.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var attributeOutsideTextFont = attributes.outsidetextfont;
1414
var helpers = require('./helpers');
1515

1616
function style(gd) {
17-
var s = d3.select(gd).selectAll('g.barlayer').selectAll('g.trace');
17+
var s = d3.select(gd).selectAll('g[class^="barlayer"]').selectAll('g.trace');
1818
resizeText(gd, s, 'bar');
1919

2020
var barcount = s.size();

src/traces/scatter/attributes.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,4 +686,14 @@ module.exports = {
686686
arrayOk: true,
687687
description: 'Sets the text font.'
688688
}),
689+
zindex: {
690+
valType: 'integer',
691+
dflt: 0,
692+
editType: 'calc',
693+
description: [
694+
'Sets the layer on which this trace is displayed, relative to ',
695+
'other traces on the same axes. Traces with higher `zindex` ',
696+
'appear in front of those with lower `zindex`.'
697+
].join(' ')
698+
}
689699
};

src/traces/scatter/defaults.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
3030
coerce('xhoverformat');
3131
coerce('yhoverformat');
3232

33+
coerce('zindex');
34+
3335
var stackGroupOpts = handleStackDefaults(traceIn, traceOut, layout, coerce);
3436
if(
3537
layout.scattermode === 'group' &&

test/image/mocks/zindex_basic.json

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"data": [
3+
{
4+
"x": [2, 3, 4, 5],
5+
"y": [4, 3, 9, 5],
6+
"name": "blue",
7+
"type": "scatter",
8+
"marker": {"size": 20},
9+
"line": {"width": 6},
10+
"zindex": 5
11+
},
12+
{
13+
"x": [2, 3, 4, 5, 6],
14+
"y": [2, 5, 4, 6, 4],
15+
"name": "orange",
16+
"type": "scatter",
17+
"marker": {"size": 20},
18+
"line": {"width": 6},
19+
"zindex": 4
20+
},
21+
{
22+
"x": [3, 4, 5, 6, 7],
23+
"y": [1, 8, 6, 8, 5],
24+
"name": "green",
25+
"type": "scatter",
26+
"marker": {"size": 20},
27+
"line": {"width": 6}
28+
},
29+
{
30+
"x": [4, 5, 6, 7],
31+
"y": [2, 8, 2, 7],
32+
"name": "red",
33+
"type": "scatter",
34+
"marker": {"size": 20},
35+
"line": {"width": 6},
36+
"zindex": 300
37+
},
38+
{
39+
"x": [2, 3, 4, 5, 6, 7],
40+
"y": [4, 2, 6, 1, 6, 9],
41+
"name": "purple",
42+
"type": "bar",
43+
"zindex": 6
44+
}
45+
],
46+
"layout": {
47+
"xaxis": {
48+
"title": {
49+
"text": "zindex stacking"
50+
}
51+
}
52+
}
53+
}

0 commit comments

Comments
 (0)