From 440ca0de56402646d26c5a0c41dd4fa78c7cc8db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 11 Feb 2019 14:51:20 -0500 Subject: [PATCH 1/3] throw error when setting transform attrs with NaNs --- test/image/strict-d3.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/image/strict-d3.js b/test/image/strict-d3.js index 28154ea7c98..5672f830a9d 100644 --- a/test/image/strict-d3.js +++ b/test/image/strict-d3.js @@ -58,6 +58,10 @@ function checkAttrVal(sel, key, val) { if(/--/.test(val) && isNumeric(val.split('--')[1].charAt(0))) { throw new Error('d3 selection.attr called with value ' + val + ' which includes a double negative'); } + + if(/transform/.test(key) && /NaN/.test(val)) { + throw new Error('d3 selection.attr called with ' + key + ' ' + val + ' containing a NaN'); + } } function checkStyleVal(sel, key, val) { From 6c9ba1a73b6691b2cd6ba4aa2279e3209209a2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 11 Feb 2019 14:53:50 -0500 Subject: [PATCH 2/3] call ax.setScale in Annotations.drawOne ... which happens to be the first time it's called when annotations are present on autoranged axes on subplots w/o visible traces. This is important to avoid `transform:rotate(NaN)` errors as annotations require ax._offset to first-draw text to compute its bounds. --- src/components/annotations/draw.js | 3 +++ test/jasmine/tests/annotations_test.js | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/components/annotations/draw.js b/src/components/annotations/draw.js index dfb0647e0cd..96c6008456c 100644 --- a/src/components/annotations/draw.js +++ b/src/components/annotations/draw.js @@ -67,6 +67,9 @@ function drawOne(gd, index) { var xa = Axes.getFromId(gd, options.xref); var ya = Axes.getFromId(gd, options.yref); + if(xa) xa.setScale(); + if(ya) ya.setScale(); + drawRaw(gd, options, index, false, xa, ya); } diff --git a/test/jasmine/tests/annotations_test.js b/test/jasmine/tests/annotations_test.js index d6c11e6c6e7..8859520e5d0 100644 --- a/test/jasmine/tests/annotations_test.js +++ b/test/jasmine/tests/annotations_test.js @@ -814,6 +814,28 @@ describe('annotations autorange', function() { .catch(failTest) .then(done); }); + + it('should not error out on subplots w/o visible traces', function(done) { + Plotly.plot(gd, [{}], { + annotations: [{ + x: 0.1, + y: 0.1, + text: 't', + showarrow: false + }, { + x: 0.2, + y: 0.3, + text: 'a' + }] + }) + .then(function() { + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.099, 0.201], 1, 'x rng'); + expect(gd._fullLayout.yaxis.range).toBeCloseToArray([0.091, 0.335], 1, 'y rng'); + assertVisible([0, 1]); + }) + .catch(failTest) + .then(done); + }); }); describe('annotation clicktoshow', function() { From a35500a7c597cddbe3781f7f248c4aa0dd7e8366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 11 Feb 2019 14:54:45 -0500 Subject: [PATCH 3/3] fix trace-less scenes with 3d annotations - this is an unreported bug, that the new strict-d3 logic uncovered. --- src/plots/gl3d/scene.js | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/plots/gl3d/scene.js b/src/plots/gl3d/scene.js index 94a7ef40362..5d3ebe23297 100644 --- a/src/plots/gl3d/scene.js +++ b/src/plots/gl3d/scene.js @@ -399,6 +399,29 @@ function computeTraceBounds(scene, trace, bounds) { } } +function computeAnnotationBounds(scene, bounds) { + var sceneLayout = scene.fullSceneLayout; + var annotations = sceneLayout.annotations || []; + + for(var d = 0; d < 3; d++) { + var axisName = axisProperties[d]; + var axLetter = axisName.charAt(0); + var ax = sceneLayout[axisName]; + + for(var j = 0; j < annotations.length; j++) { + var ann = annotations[j]; + + if(ann.visible) { + var pos = ax.r2l(ann[axLetter]); + if(!isNaN(pos) && isFinite(pos)) { + bounds[0][d] = Math.min(bounds[0][d], pos); + bounds[1][d] = Math.max(bounds[1][d], pos); + } + } + } + } +} + proto.plot = function(sceneData, fullLayout, layout) { // Save parameters this.plotArgs = [sceneData, fullLayout, layout]; @@ -443,18 +466,20 @@ proto.plot = function(sceneData, fullLayout, layout) { [Infinity, Infinity, Infinity], [-Infinity, -Infinity, -Infinity] ]; + for(i = 0; i < sceneData.length; ++i) { data = sceneData[i]; if(data.visible !== true) continue; computeTraceBounds(this, data, dataBounds); } + computeAnnotationBounds(this, dataBounds); + var dataScale = [1, 1, 1]; for(j = 0; j < 3; ++j) { if(dataBounds[1][j] === dataBounds[0][j]) { dataScale[j] = 1.0; - } - else { + } else { dataScale[j] = 1.0 / (dataBounds[1][j] - dataBounds[0][j]); } }