From 472225fc2c64876b058adee9ddd82e188e5bff0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Etienne=20T=C3=A9treault-Pinard?= Date: Tue, 15 Aug 2017 13:44:46 -0400 Subject: [PATCH 1/3] implement `layer: 'below traces'` for ternary axes - to do so, rm and construct plot-layer data based on ax.layer - make sure layer order is updated on ternary.plot using selection.order() - grab layer ref from `this.layers` when possible, to undo useless querySelector calls. --- src/plots/ternary/layout/axis_attributes.js | 1 + src/plots/ternary/layout/axis_defaults.js | 2 + src/plots/ternary/ternary.js | 101 +++++++++++++------- 3 files changed, 67 insertions(+), 37 deletions(-) diff --git a/src/plots/ternary/layout/axis_attributes.js b/src/plots/ternary/layout/axis_attributes.js index 05d34dfef19..fa35570ecb3 100644 --- a/src/plots/ternary/layout/axis_attributes.js +++ b/src/plots/ternary/layout/axis_attributes.js @@ -47,6 +47,7 @@ module.exports = { showgrid: extendFlat({}, axesAttrs.showgrid, {dflt: true}), gridcolor: axesAttrs.gridcolor, gridwidth: axesAttrs.gridwidth, + layer: axesAttrs.layer, // range min: { valType: 'number', diff --git a/src/plots/ternary/layout/axis_defaults.js b/src/plots/ternary/layout/axis_defaults.js index 0ed502a839e..0a02d2260b5 100644 --- a/src/plots/ternary/layout/axis_defaults.js +++ b/src/plots/ternary/layout/axis_defaults.js @@ -79,4 +79,6 @@ module.exports = function supplyLayoutDefaults(containerIn, containerOut, option coerce('gridcolor', colorMix(dfltColor, options.bgColor, 60).toRgbString()); coerce('gridwidth'); } + + coerce('layer'); }; diff --git a/src/plots/ternary/ternary.js b/src/plots/ternary/ternary.js index c5840d5e9ec..719b89168a7 100644 --- a/src/plots/ternary/ternary.js +++ b/src/plots/ternary/ternary.js @@ -31,7 +31,7 @@ function Ternary(options, fullLayout) { this.id = options.id; this.graphDiv = options.graphDiv; this.init(fullLayout); - this.makeFramework(); + this.makeFramework(fullLayout); } module.exports = Ternary; @@ -43,6 +43,7 @@ proto.init = function(fullLayout) { this.defs = fullLayout._defs; this.layoutId = fullLayout._uid; this.traceHash = {}; + this.layers = {}; }; proto.plot = function(ternaryCalcData, fullLayout) { @@ -60,15 +61,15 @@ proto.plot = function(ternaryCalcData, fullLayout) { } } + _this.updateLayers(ternaryLayout); _this.adjustLayout(ternaryLayout, graphSize); - Plots.generalUpdatePerTraceModule(_this, ternaryCalcData, ternaryLayout); - _this.layers.plotbg.select('path').call(Color.fill, ternaryLayout.bgcolor); }; -proto.makeFramework = function() { +proto.makeFramework = function(fullLayout) { var _this = this; + var ternaryLayout = fullLayout[_this.id]; var defGroup = _this.defs.selectAll('g.clips') .data([0]); @@ -95,50 +96,75 @@ proto.makeFramework = function() { _this.plotContainer.enter().append('g') .classed(_this.id, true); - _this.layers = {}; + _this.updateLayers(ternaryLayout); + + Drawing.setClipUrl(_this.layers.backplot, clipId); + Drawing.setClipUrl(_this.layers.grids, clipId); +}; + +proto.updateLayers = function(ternaryLayout) { + var _this = this; + var layers = _this.layers; // inside that container, we have one container for the data, and // one each for the three axes around it. - var plotLayers = [ - 'draglayer', - 'plotbg', - 'backplot', - 'grids', - 'frontplot', - 'aaxis', 'baxis', 'caxis', 'axlines' - ]; + + var plotLayers = ['draglayer', 'plotbg', 'backplot', 'grids']; + + if(ternaryLayout.aaxis.layer === 'below traces') { + plotLayers.push('aaxis', 'aline'); + } + if(ternaryLayout.baxis.layer === 'below traces') { + plotLayers.push('baxis', 'bline'); + } + if(ternaryLayout.caxis.layer === 'below traces') { + plotLayers.push('caxis', 'cline'); + } + + plotLayers.push('frontplot'); + + if(ternaryLayout.aaxis.layer === 'above traces') { + plotLayers.push('aaxis', 'aline'); + } + if(ternaryLayout.baxis.layer === 'above traces') { + plotLayers.push('baxis', 'bline'); + } + if(ternaryLayout.caxis.layer === 'above traces') { + plotLayers.push('caxis', 'cline'); + } + var toplevel = _this.plotContainer.selectAll('g.toplevel') - .data(plotLayers); + .data(plotLayers, String); + + var grids = ['agrid', 'bgrid', 'cgrid']; + toplevel.enter().append('g') .attr('class', function(d) { return 'toplevel ' + d; }) .each(function(d) { var s = d3.select(this); - _this.layers[d] = s; + layers[d] = s; // containers for different trace types. // NOTE - this is different from cartesian, where all traces // are in front of grids. Here I'm putting maps behind the grids // so the grids will always be visible if they're requested. // Perhaps we want that for cartesian too? - if(d === 'frontplot') s.append('g').classed('scatterlayer', true); - else if(d === 'backplot') s.append('g').classed('maplayer', true); - else if(d === 'plotbg') s.append('path').attr('d', 'M0,0Z'); - else if(d === 'axlines') { - s.selectAll('path').data(['aline', 'bline', 'cline']) - .enter().append('path').each(function(d) { - d3.select(this).classed(d, true); - }); + if(d === 'frontplot') { + s.append('g').classed('scatterlayer', true); + } else if(d === 'backplot') { + s.append('g').classed('maplayer', true); + } else if(d === 'plotbg') { + s.append('path').attr('d', 'M0,0Z'); + } else if(d === 'aline' || d === 'bline' || d === 'cline') { + s.append('path'); + } else if(d === 'grids') { + grids.forEach(function(d) { + layers[d] = s.append('g').classed('grid ' + d, true); + }); } }); - var grids = _this.plotContainer.select('.grids').selectAll('g.grid') - .data(['agrid', 'bgrid', 'cgrid']); - grids.enter().append('g') - .attr('class', function(d) { return 'grid ' + d; }) - .each(function(d) { _this.layers[d] = d3.select(this); }); - - _this.plotContainer.selectAll('.backplot,.grids') - .call(Drawing.setClipUrl, clipId); + toplevel.order(); }; var w_over_h = Math.sqrt(4 / 3); @@ -315,18 +341,17 @@ proto.adjustLayout = function(ternaryLayout, graphSize) { // make these counterproductive. _this.plotContainer.selectAll('.crisp').classed('crisp', false); - var axlines = _this.layers.axlines; - axlines.select('.aline') + _this.layers.aline.select('path') .attr('d', aaxis.showline ? 'M' + x0 + ',' + (y0 + h) + 'l' + (w / 2) + ',-' + h : 'M0,0') .call(Color.stroke, aaxis.linecolor || '#000') .style('stroke-width', (aaxis.linewidth || 0) + 'px'); - axlines.select('.bline') + _this.layers.bline.select('path') .attr('d', baxis.showline ? 'M' + x0 + ',' + (y0 + h) + 'h' + w : 'M0,0') .call(Color.stroke, baxis.linecolor || '#000') .style('stroke-width', (baxis.linewidth || 0) + 'px'); - axlines.select('.cline') + _this.layers.cline.select('path') .attr('d', caxis.showline ? 'M' + (x0 + w / 2) + ',' + y0 + 'l' + (w / 2) + ',' + h : 'M0,0') .call(Color.stroke, caxis.linecolor || '#000') @@ -336,8 +361,10 @@ proto.adjustLayout = function(ternaryLayout, graphSize) { _this.initInteractions(); } - _this.plotContainer.select('.frontplot') - .call(Drawing.setClipUrl, _this._hasClipOnAxisFalse ? null : _this.clipId); + Drawing.setClipUrl( + _this.layers.frontplot, + _this._hasClipOnAxisFalse ? null : _this.clipId + ); }; proto.drawAxes = function(doTitles) { From f6dd5d5debabeb13b7eeb83e50a37e384236ab2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Etienne=20T=C3=A9treault-Pinard?= Date: Tue, 15 Aug 2017 13:44:55 -0400 Subject: [PATCH 2/3] add ternary axis layer mock --- test/image/baselines/ternary_axis_layers.png | Bin 0 -> 29714 bytes test/image/mocks/ternary_axis_layers.json | 59 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 test/image/baselines/ternary_axis_layers.png create mode 100644 test/image/mocks/ternary_axis_layers.json diff --git a/test/image/baselines/ternary_axis_layers.png b/test/image/baselines/ternary_axis_layers.png new file mode 100644 index 0000000000000000000000000000000000000000..e2e02dbf1b1d08d568715b0d493085e976d07cf7 GIT binary patch literal 29714 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 z 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 Date: Tue, 15 Aug 2017 14:46:32 -0400 Subject: [PATCH 3/3] add jasmine test for ternary 'layer' --- test/jasmine/tests/ternary_test.js | 74 +++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/test/jasmine/tests/ternary_test.js b/test/jasmine/tests/ternary_test.js index ade4abf3d2c..5140fdf40ab 100644 --- a/test/jasmine/tests/ternary_test.js +++ b/test/jasmine/tests/ternary_test.js @@ -6,13 +6,13 @@ var supplyLayoutDefaults = require('@src/plots/ternary/layout/defaults'); var d3 = require('d3'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); +var fail = require('../assets/fail_test'); var mouseEvent = require('../assets/mouse_event'); var click = require('../assets/click'); var doubleClick = require('../assets/double_click'); var customMatchers = require('../assets/custom_matchers'); var getClientPosition = require('../assets/get_client_position'); - describe('ternary plots', function() { 'use strict'; @@ -244,6 +244,78 @@ describe('ternary plots', function() { }); }); + it('should be able to reorder axis layers when relayout\'ing *layer*', function(done) { + var gd = createGraphDiv(); + var fig = Lib.extendDeep({}, require('@mocks/ternary_simple.json')); + var dflt = [ + 'draglayer', 'plotbg', 'backplot', 'grids', + 'frontplot', + 'aaxis', 'aline', 'baxis', 'bline', 'caxis', 'cline' + ]; + + function _assert(layers) { + var toplevel = d3.selectAll('g.ternary > .toplevel'); + + expect(toplevel.size()).toBe(layers.length, '# of layer'); + + toplevel.each(function(d, i) { + var className = d3.select(this) + .attr('class') + .split('toplevel ')[1]; + + expect(className).toBe(layers[i], 'layer ' + i); + }); + } + + Plotly.plot(gd, fig).then(function() { + _assert(dflt); + return Plotly.relayout(gd, 'ternary.aaxis.layer', 'below traces'); + }) + .then(function() { + _assert([ + 'draglayer', 'plotbg', 'backplot', 'grids', + 'aaxis', 'aline', + 'frontplot', + 'baxis', 'bline', 'caxis', 'cline' + ]); + return Plotly.relayout(gd, 'ternary.caxis.layer', 'below traces'); + }) + .then(function() { + _assert([ + 'draglayer', 'plotbg', 'backplot', 'grids', + 'aaxis', 'aline', 'caxis', 'cline', + 'frontplot', + 'baxis', 'bline' + ]); + return Plotly.relayout(gd, 'ternary.baxis.layer', 'below traces'); + }) + .then(function() { + _assert([ + 'draglayer', 'plotbg', 'backplot', 'grids', + 'aaxis', 'aline', 'baxis', 'bline', 'caxis', 'cline', + 'frontplot' + ]); + return Plotly.relayout(gd, 'ternary.aaxis.layer', null); + }) + .then(function() { + _assert([ + 'draglayer', 'plotbg', 'backplot', 'grids', + 'baxis', 'bline', 'caxis', 'cline', + 'frontplot', + 'aaxis', 'aline' + ]); + return Plotly.relayout(gd, { + 'ternary.baxis.layer': null, + 'ternary.caxis.layer': null + }); + }) + .then(function() { + _assert(dflt); + }) + .catch(fail) + .then(done); + }); + function countTernarySubplot() { return d3.selectAll('.ternary').size(); }