Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 885c545

Browse filesBrowse files
authored
Merge pull request plotly#1952 from plotly/ternary-axis-layer
Ternary axis layer
2 parents 4ae95dd + 9efb321 commit 885c545
Copy full SHA for 885c545

File tree

Expand file treeCollapse file tree

6 files changed

+199
-38
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+199
-38
lines changed

‎src/plots/ternary/layout/axis_attributes.js

Copy file name to clipboardExpand all lines: src/plots/ternary/layout/axis_attributes.js
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ module.exports = {
4747
showgrid: extendFlat({}, axesAttrs.showgrid, {dflt: true}),
4848
gridcolor: axesAttrs.gridcolor,
4949
gridwidth: axesAttrs.gridwidth,
50+
layer: axesAttrs.layer,
5051
// range
5152
min: {
5253
valType: 'number',

‎src/plots/ternary/layout/axis_defaults.js

Copy file name to clipboardExpand all lines: src/plots/ternary/layout/axis_defaults.js
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,6 @@ module.exports = function supplyLayoutDefaults(containerIn, containerOut, option
7979
coerce('gridcolor', colorMix(dfltColor, options.bgColor, 60).toRgbString());
8080
coerce('gridwidth');
8181
}
82+
83+
coerce('layer');
8284
};

‎src/plots/ternary/ternary.js

Copy file name to clipboardExpand all lines: src/plots/ternary/ternary.js
+64-37Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function Ternary(options, fullLayout) {
3131
this.id = options.id;
3232
this.graphDiv = options.graphDiv;
3333
this.init(fullLayout);
34-
this.makeFramework();
34+
this.makeFramework(fullLayout);
3535
}
3636

3737
module.exports = Ternary;
@@ -43,6 +43,7 @@ proto.init = function(fullLayout) {
4343
this.defs = fullLayout._defs;
4444
this.layoutId = fullLayout._uid;
4545
this.traceHash = {};
46+
this.layers = {};
4647
};
4748

4849
proto.plot = function(ternaryCalcData, fullLayout) {
@@ -60,15 +61,15 @@ proto.plot = function(ternaryCalcData, fullLayout) {
6061
}
6162
}
6263

64+
_this.updateLayers(ternaryLayout);
6365
_this.adjustLayout(ternaryLayout, graphSize);
64-
6566
Plots.generalUpdatePerTraceModule(_this, ternaryCalcData, ternaryLayout);
66-
6767
_this.layers.plotbg.select('path').call(Color.fill, ternaryLayout.bgcolor);
6868
};
6969

70-
proto.makeFramework = function() {
70+
proto.makeFramework = function(fullLayout) {
7171
var _this = this;
72+
var ternaryLayout = fullLayout[_this.id];
7273

7374
var defGroup = _this.defs.selectAll('g.clips')
7475
.data([0]);
@@ -95,50 +96,75 @@ proto.makeFramework = function() {
9596
_this.plotContainer.enter().append('g')
9697
.classed(_this.id, true);
9798

98-
_this.layers = {};
99+
_this.updateLayers(ternaryLayout);
100+
101+
Drawing.setClipUrl(_this.layers.backplot, clipId);
102+
Drawing.setClipUrl(_this.layers.grids, clipId);
103+
};
104+
105+
proto.updateLayers = function(ternaryLayout) {
106+
var _this = this;
107+
var layers = _this.layers;
99108

100109
// inside that container, we have one container for the data, and
101110
// one each for the three axes around it.
102-
var plotLayers = [
103-
'draglayer',
104-
'plotbg',
105-
'backplot',
106-
'grids',
107-
'frontplot',
108-
'aaxis', 'baxis', 'caxis', 'axlines'
109-
];
111+
112+
var plotLayers = ['draglayer', 'plotbg', 'backplot', 'grids'];
113+
114+
if(ternaryLayout.aaxis.layer === 'below traces') {
115+
plotLayers.push('aaxis', 'aline');
116+
}
117+
if(ternaryLayout.baxis.layer === 'below traces') {
118+
plotLayers.push('baxis', 'bline');
119+
}
120+
if(ternaryLayout.caxis.layer === 'below traces') {
121+
plotLayers.push('caxis', 'cline');
122+
}
123+
124+
plotLayers.push('frontplot');
125+
126+
if(ternaryLayout.aaxis.layer === 'above traces') {
127+
plotLayers.push('aaxis', 'aline');
128+
}
129+
if(ternaryLayout.baxis.layer === 'above traces') {
130+
plotLayers.push('baxis', 'bline');
131+
}
132+
if(ternaryLayout.caxis.layer === 'above traces') {
133+
plotLayers.push('caxis', 'cline');
134+
}
135+
110136
var toplevel = _this.plotContainer.selectAll('g.toplevel')
111-
.data(plotLayers);
137+
.data(plotLayers, String);
138+
139+
var grids = ['agrid', 'bgrid', 'cgrid'];
140+
112141
toplevel.enter().append('g')
113142
.attr('class', function(d) { return 'toplevel ' + d; })
114143
.each(function(d) {
115144
var s = d3.select(this);
116-
_this.layers[d] = s;
145+
layers[d] = s;
117146

118147
// containers for different trace types.
119148
// NOTE - this is different from cartesian, where all traces
120149
// are in front of grids. Here I'm putting maps behind the grids
121150
// so the grids will always be visible if they're requested.
122151
// Perhaps we want that for cartesian too?
123-
if(d === 'frontplot') s.append('g').classed('scatterlayer', true);
124-
else if(d === 'backplot') s.append('g').classed('maplayer', true);
125-
else if(d === 'plotbg') s.append('path').attr('d', 'M0,0Z');
126-
else if(d === 'axlines') {
127-
s.selectAll('path').data(['aline', 'bline', 'cline'])
128-
.enter().append('path').each(function(d) {
129-
d3.select(this).classed(d, true);
130-
});
152+
if(d === 'frontplot') {
153+
s.append('g').classed('scatterlayer', true);
154+
} else if(d === 'backplot') {
155+
s.append('g').classed('maplayer', true);
156+
} else if(d === 'plotbg') {
157+
s.append('path').attr('d', 'M0,0Z');
158+
} else if(d === 'aline' || d === 'bline' || d === 'cline') {
159+
s.append('path');
160+
} else if(d === 'grids') {
161+
grids.forEach(function(d) {
162+
layers[d] = s.append('g').classed('grid ' + d, true);
163+
});
131164
}
132165
});
133166

134-
var grids = _this.plotContainer.select('.grids').selectAll('g.grid')
135-
.data(['agrid', 'bgrid', 'cgrid']);
136-
grids.enter().append('g')
137-
.attr('class', function(d) { return 'grid ' + d; })
138-
.each(function(d) { _this.layers[d] = d3.select(this); });
139-
140-
_this.plotContainer.selectAll('.backplot,.grids')
141-
.call(Drawing.setClipUrl, clipId);
167+
toplevel.order();
142168
};
143169

144170
var w_over_h = Math.sqrt(4 / 3);
@@ -315,18 +341,17 @@ proto.adjustLayout = function(ternaryLayout, graphSize) {
315341
// make these counterproductive.
316342
_this.plotContainer.selectAll('.crisp').classed('crisp', false);
317343

318-
var axlines = _this.layers.axlines;
319-
axlines.select('.aline')
344+
_this.layers.aline.select('path')
320345
.attr('d', aaxis.showline ?
321346
'M' + x0 + ',' + (y0 + h) + 'l' + (w / 2) + ',-' + h : 'M0,0')
322347
.call(Color.stroke, aaxis.linecolor || '#000')
323348
.style('stroke-width', (aaxis.linewidth || 0) + 'px');
324-
axlines.select('.bline')
349+
_this.layers.bline.select('path')
325350
.attr('d', baxis.showline ?
326351
'M' + x0 + ',' + (y0 + h) + 'h' + w : 'M0,0')
327352
.call(Color.stroke, baxis.linecolor || '#000')
328353
.style('stroke-width', (baxis.linewidth || 0) + 'px');
329-
axlines.select('.cline')
354+
_this.layers.cline.select('path')
330355
.attr('d', caxis.showline ?
331356
'M' + (x0 + w / 2) + ',' + y0 + 'l' + (w / 2) + ',' + h : 'M0,0')
332357
.call(Color.stroke, caxis.linecolor || '#000')
@@ -336,8 +361,10 @@ proto.adjustLayout = function(ternaryLayout, graphSize) {
336361
_this.initInteractions();
337362
}
338363

339-
_this.plotContainer.select('.frontplot')
340-
.call(Drawing.setClipUrl, _this._hasClipOnAxisFalse ? null : _this.clipId);
364+
Drawing.setClipUrl(
365+
_this.layers.frontplot,
366+
_this._hasClipOnAxisFalse ? null : _this.clipId
367+
);
341368
};
342369

343370
proto.drawAxes = function(doTitles) {
29 KB
Loading
+59Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"data": [
3+
{
4+
"type": "scatterternary",
5+
"mode": "markers",
6+
"a": [70, 75, 5, 10],
7+
"b": [10, 20, 60, 80],
8+
"c": [20, 5, 35, 10],
9+
"name": "not clipped",
10+
"marker": {
11+
"symbol": "square",
12+
"size": 40,
13+
"line": { "width": 4 }
14+
},
15+
"cliponaxis": false
16+
},
17+
{
18+
"type": "scatterternary",
19+
"mode": "markers",
20+
"name": "clipped",
21+
"a": [10, 20, 10, 15, 10, 20],
22+
"b": [90, 70, 20, 5, 10, 10],
23+
"c": [0, 10, 70, 80, 80, 70],
24+
"marker": {
25+
"symbol": "diamond",
26+
"size": 30,
27+
"line": { "width": 4 }
28+
},
29+
"cliponaxis": true
30+
}
31+
],
32+
"layout": {
33+
"ternary": {
34+
"sum": 100,
35+
"aaxis": {
36+
"title": "",
37+
"layer": "below traces",
38+
"linewidth": 4,
39+
"min": 4.5
40+
},
41+
"baxis": {
42+
"title": "",
43+
"layer": "below traces",
44+
"linewidth": 4,
45+
"min": 7.5
46+
},
47+
"caxis": {
48+
"title": "",
49+
"layer": "below traces",
50+
"linewidth": 4,
51+
"min": 7.5
52+
}
53+
},
54+
"title": "ternary axes below traces",
55+
"showlegend": false,
56+
"height": 450,
57+
"width": 500
58+
}
59+
}

‎test/jasmine/tests/ternary_test.js

Copy file name to clipboardExpand all lines: test/jasmine/tests/ternary_test.js
+73-1Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ var supplyLayoutDefaults = require('@src/plots/ternary/layout/defaults');
66
var d3 = require('d3');
77
var createGraphDiv = require('../assets/create_graph_div');
88
var destroyGraphDiv = require('../assets/destroy_graph_div');
9+
var fail = require('../assets/fail_test');
910
var mouseEvent = require('../assets/mouse_event');
1011
var click = require('../assets/click');
1112
var doubleClick = require('../assets/double_click');
1213
var customMatchers = require('../assets/custom_matchers');
1314
var getClientPosition = require('../assets/get_client_position');
1415

15-
1616
describe('ternary plots', function() {
1717
'use strict';
1818

@@ -244,6 +244,78 @@ describe('ternary plots', function() {
244244
});
245245
});
246246

247+
it('should be able to reorder axis layers when relayout\'ing *layer*', function(done) {
248+
var gd = createGraphDiv();
249+
var fig = Lib.extendDeep({}, require('@mocks/ternary_simple.json'));
250+
var dflt = [
251+
'draglayer', 'plotbg', 'backplot', 'grids',
252+
'frontplot',
253+
'aaxis', 'aline', 'baxis', 'bline', 'caxis', 'cline'
254+
];
255+
256+
function _assert(layers) {
257+
var toplevel = d3.selectAll('g.ternary > .toplevel');
258+
259+
expect(toplevel.size()).toBe(layers.length, '# of layer');
260+
261+
toplevel.each(function(d, i) {
262+
var className = d3.select(this)
263+
.attr('class')
264+
.split('toplevel ')[1];
265+
266+
expect(className).toBe(layers[i], 'layer ' + i);
267+
});
268+
}
269+
270+
Plotly.plot(gd, fig).then(function() {
271+
_assert(dflt);
272+
return Plotly.relayout(gd, 'ternary.aaxis.layer', 'below traces');
273+
})
274+
.then(function() {
275+
_assert([
276+
'draglayer', 'plotbg', 'backplot', 'grids',
277+
'aaxis', 'aline',
278+
'frontplot',
279+
'baxis', 'bline', 'caxis', 'cline'
280+
]);
281+
return Plotly.relayout(gd, 'ternary.caxis.layer', 'below traces');
282+
})
283+
.then(function() {
284+
_assert([
285+
'draglayer', 'plotbg', 'backplot', 'grids',
286+
'aaxis', 'aline', 'caxis', 'cline',
287+
'frontplot',
288+
'baxis', 'bline'
289+
]);
290+
return Plotly.relayout(gd, 'ternary.baxis.layer', 'below traces');
291+
})
292+
.then(function() {
293+
_assert([
294+
'draglayer', 'plotbg', 'backplot', 'grids',
295+
'aaxis', 'aline', 'baxis', 'bline', 'caxis', 'cline',
296+
'frontplot'
297+
]);
298+
return Plotly.relayout(gd, 'ternary.aaxis.layer', null);
299+
})
300+
.then(function() {
301+
_assert([
302+
'draglayer', 'plotbg', 'backplot', 'grids',
303+
'baxis', 'bline', 'caxis', 'cline',
304+
'frontplot',
305+
'aaxis', 'aline'
306+
]);
307+
return Plotly.relayout(gd, {
308+
'ternary.baxis.layer': null,
309+
'ternary.caxis.layer': null
310+
});
311+
})
312+
.then(function() {
313+
_assert(dflt);
314+
})
315+
.catch(fail)
316+
.then(done);
317+
});
318+
247319
function countTernarySubplot() {
248320
return d3.selectAll('.ternary').size();
249321
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.