From c4b811ca6494a1dbf8a60c104f807a6757993213 Mon Sep 17 00:00:00 2001 From: archmoj Date: Wed, 18 Mar 2020 16:55:50 -0400 Subject: [PATCH 1/4] ensure waterfall connector lines cliped when there is an axis break --- src/traces/waterfall/plot.js | 44 ++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/traces/waterfall/plot.js b/src/traces/waterfall/plot.js index 006bc9e93aa..065ff77bb0a 100644 --- a/src/traces/waterfall/plot.js +++ b/src/traces/waterfall/plot.js @@ -11,6 +11,7 @@ var d3 = require('d3'); var Lib = require('../../lib'); var Drawing = require('../../components/drawing'); +var BADNUM = require('../../constants/numerical').BADNUM; var barPlot = require('../bar/plot'); var clearMinTextSize = require('../bar/uniform_text').clearMinTextSize; @@ -66,31 +67,36 @@ function plotConnectors(gd, plotinfo, cdModule, traceLayer) { var shape = ''; - if(mode === 'spanning') { - if(!di.isSum && i > 0) { - if(isHorizontal) { - shape += 'M' + x[0] + ',' + y[1] + 'V' + y[0]; - } else { - shape += 'M' + x[1] + ',' + y[0] + 'H' + x[0]; + if( + x[0] !== BADNUM && y[0] !== BADNUM && + x[1] !== BADNUM && y[1] !== BADNUM + ) { + if(mode === 'spanning') { + if(!di.isSum && i > 0) { + if(isHorizontal) { + shape += 'M' + x[0] + ',' + y[1] + 'V' + y[0]; + } else { + shape += 'M' + x[1] + ',' + y[0] + 'H' + x[0]; + } } } - } - if(mode !== 'between') { - if(di.isSum || i < len - 1) { - if(isHorizontal) { - shape += 'M' + x[1] + ',' + y[0] + 'V' + y[1]; - } else { - shape += 'M' + x[0] + ',' + y[1] + 'H' + x[1]; + if(mode !== 'between') { + if(di.isSum || i < len - 1) { + if(isHorizontal) { + shape += 'M' + x[1] + ',' + y[0] + 'V' + y[1]; + } else { + shape += 'M' + x[0] + ',' + y[1] + 'H' + x[1]; + } } } - } - if(x[2] !== undefined && y[2] !== undefined) { - if(isHorizontal) { - shape += 'M' + x[1] + ',' + y[1] + 'V' + y[2]; - } else { - shape += 'M' + x[1] + ',' + y[1] + 'H' + x[2]; + if(x[2] !== BADNUM && y[2] !== BADNUM) { + if(isHorizontal) { + shape += 'M' + x[1] + ',' + y[1] + 'V' + y[2]; + } else { + shape += 'M' + x[1] + ',' + y[1] + 'H' + x[2]; + } } } From 49a960597e965889260f5cb5ee726fe054cbdb46 Mon Sep 17 00:00:00 2001 From: archmoj Date: Thu, 19 Mar 2020 12:04:48 -0400 Subject: [PATCH 2/4] add test waterfall handle BADNUM positions - can extend the test when transitions are enabled for waterfalls --- test/jasmine/tests/bar_test.js | 2 +- test/jasmine/tests/waterfall_test.js | 49 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/test/jasmine/tests/bar_test.js b/test/jasmine/tests/bar_test.js index 39cc38d4d04..d7198a5ebf6 100644 --- a/test/jasmine/tests/bar_test.js +++ b/test/jasmine/tests/bar_test.js @@ -2932,7 +2932,7 @@ describe('bar tweening', function() { .then(done); }); - it('handle NaN positions on vertical bars', function(done) { + it('handle BADNUM positions on vertical bars', function(done) { var y1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var y2 = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; var mockCopy = { diff --git a/test/jasmine/tests/waterfall_test.js b/test/jasmine/tests/waterfall_test.js index c9877e655c7..6e20e81a9d4 100644 --- a/test/jasmine/tests/waterfall_test.js +++ b/test/jasmine/tests/waterfall_test.js @@ -17,6 +17,7 @@ var rgb = color.rgb; var customAssertions = require('../assets/custom_assertions'); var assertHoverLabelContent = customAssertions.assertHoverLabelContent; var checkTextTemplate = require('../assets/check_texttemplate'); +var checkTransition = require('../assets/check_transitions'); var Fx = require('@src/components/fx'); var d3 = require('d3'); @@ -977,6 +978,54 @@ describe('A waterfall plot', function() { .then(done); }); + it('handle BADNUM positions', function(done) { + var y1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + var y2 = y1; // no transition now + var mockCopy = { + data: [ + { + type: 'waterfall', + x: [ + 0, + 1, + '', + 'NaN', + NaN, + Infinity, + -Infinity, + undefined, + null, + 9, + 10 + ], + y: y1 + } + ], + layout: { + width: 400, + height: 300 + } + }; + + var barTests = [ + [0, '.point path', 'attr', 'd', ['M2,121V109H20V121Z', 'M24,111V98H41V111Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M199,28V15H216V28Z', 'M220,17V5H238V17Z']] + ]; + + var connectorTests = [ + [0, '.line path', 'attr', 'd', ['M20,110H24', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M216,16H220', 'M0,0Z']] + ]; + + var animateOpts = {data: [{y: y2}]}; + var transitionOpts = false; // use default + + checkTransition(gd, mockCopy, animateOpts, transitionOpts, barTests) + .then(function() { + return checkTransition(gd, mockCopy, animateOpts, transitionOpts, connectorTests); + }) + .catch(failTest) + .then(done); + }); + it('should be able to deal with transform that empty out the data coordinate arrays', function(done) { Plotly.plot(gd, { data: [{ From 8c1e7a13d9b63c0f15e04a22d3d5830247f1073e Mon Sep 17 00:00:00 2001 From: archmoj Date: Thu, 19 Mar 2020 12:57:52 -0400 Subject: [PATCH 3/4] fix funnel bars and connectors as well --- src/traces/funnel/plot.js | 10 ++++++- test/jasmine/tests/funnel_test.js | 49 +++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/traces/funnel/plot.js b/src/traces/funnel/plot.js index 31aa1e8f17e..9d10435090e 100644 --- a/src/traces/funnel/plot.js +++ b/src/traces/funnel/plot.js @@ -11,6 +11,7 @@ var d3 = require('d3'); var Lib = require('../../lib'); var Drawing = require('../../components/drawing'); +var BADNUM = require('../../constants/numerical').BADNUM; var barPlot = require('../bar/plot'); var clearMinTextSize = require('../bar/uniform_text').clearMinTextSize; @@ -66,7 +67,12 @@ function plotConnectorRegions(gd, plotinfo, cdModule, traceLayer) { var shape = ''; - if(x[3] !== undefined && y[3] !== undefined) { + if( + x[0] !== BADNUM && y[0] !== BADNUM && + x[1] !== BADNUM && y[1] !== BADNUM && + x[2] !== BADNUM && y[2] !== BADNUM && + x[3] !== BADNUM && y[3] !== BADNUM + ) { if(isHorizontal) { shape += 'M' + x[0] + ',' + y[1] + 'L' + x[2] + ',' + y[2] + 'H' + x[3] + 'L' + x[1] + ',' + y[1] + 'Z'; } else { @@ -74,6 +80,8 @@ function plotConnectorRegions(gd, plotinfo, cdModule, traceLayer) { } } + if(shape === '') shape = 'M0,0Z'; + Lib.ensureSingle(d3.select(this), 'path') .attr('d', shape) .call(Drawing.setClipUrl, plotinfo.layerClipId, gd); diff --git a/test/jasmine/tests/funnel_test.js b/test/jasmine/tests/funnel_test.js index 3a49a70e2c5..8d95a7ab102 100644 --- a/test/jasmine/tests/funnel_test.js +++ b/test/jasmine/tests/funnel_test.js @@ -17,6 +17,7 @@ var rgb = color.rgb; var customAssertions = require('../assets/custom_assertions'); var assertHoverLabelContent = customAssertions.assertHoverLabelContent; var checkTextTemplate = require('../assets/check_texttemplate'); +var checkTransition = require('../assets/check_transitions'); var Fx = require('@src/components/fx'); var d3 = require('d3'); @@ -1033,6 +1034,54 @@ describe('A funnel plot', function() { .then(done); }); + it('handle BADNUM positions', function(done) { + var y1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + var y2 = y1; // no transition now + var mockCopy = { + data: [ + { + type: 'funnel', + x: [ + 0, + 1, + '', + 'NaN', + NaN, + Infinity, + -Infinity, + undefined, + null, + 9, + 10 + ], + y: y1 + } + ], + layout: { + width: 400, + height: 300 + } + }; + + var barTests = [ + [0, '.point path', 'attr', 'd', ['M12,12V108H12V12Z', 'M12,12V108H23V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M23,12V108H120V12Z', 'M120,12V108H228V12Z']] + ]; + + var connectorTests = [ + [0, '.regions path', 'attr', 'd', ['M12,108L12,12H23L12,108Z', 'M23,108L120,12H228L120,108Z', 'M0,0Z']] + ]; + + var animateOpts = {data: [{y: y2}]}; + var transitionOpts = false; // use default + + checkTransition(gd, mockCopy, animateOpts, transitionOpts, barTests) + .then(function() { + return checkTransition(gd, mockCopy, animateOpts, transitionOpts, connectorTests); + }) + .catch(failTest) + .then(done); + }); + it('should be able to deal with transform that empty out the data coordinate arrays', function(done) { Plotly.plot(gd, { data: [{ From d9f0002e710bbf3e6d71eee5678853f6ecce6213 Mon Sep 17 00:00:00 2001 From: archmoj Date: Thu, 19 Mar 2020 13:49:03 -0400 Subject: [PATCH 4/4] improve funnel test - correct orientation, etc --- test/jasmine/tests/funnel_test.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/jasmine/tests/funnel_test.js b/test/jasmine/tests/funnel_test.js index 8d95a7ab102..347c494a9ac 100644 --- a/test/jasmine/tests/funnel_test.js +++ b/test/jasmine/tests/funnel_test.js @@ -1035,13 +1035,13 @@ describe('A funnel plot', function() { }); it('handle BADNUM positions', function(done) { - var y1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; - var y2 = y1; // no transition now + var x1 = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; + var x2 = x1; // no transition now var mockCopy = { data: [ { type: 'funnel', - x: [ + y: [ 0, 1, '', @@ -1054,24 +1054,24 @@ describe('A funnel plot', function() { 9, 10 ], - y: y1 + x: x1 } ], layout: { - width: 400, - height: 300 + width: 800, + height: 600 } }; var barTests = [ - [0, '.point path', 'attr', 'd', ['M12,12V108H12V12Z', 'M12,12V108H23V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M120,12V108H120V12Z', 'M23,12V108H120V12Z', 'M120,12V108H228V12Z']] + [0, '.point path', 'attr', 'd', ['M245,4V34H395V4Z', 'M251,42V73H389V42Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M306,347V378H334V347Z', 'M313,386V416H327V386Z']] ]; var connectorTests = [ - [0, '.regions path', 'attr', 'd', ['M12,108L12,12H23L12,108Z', 'M23,108L120,12H228L120,108Z', 'M0,0Z']] + [0, '.regions path', 'attr', 'd', ['M245,34L251,42H389L395,34Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M306,378L313,386H327L334,378Z', 'M0,0Z']] ]; - var animateOpts = {data: [{y: y2}]}; + var animateOpts = {data: [{x: x2}]}; var transitionOpts = false; // use default checkTransition(gd, mockCopy, animateOpts, transitionOpts, barTests)