From 5ef69b38e3759edba66b2d21fa8508221a0b0dff Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Sat, 9 Apr 2016 00:08:32 +0100 Subject: [PATCH 01/12] Remove unnecessary code in repositionLegend() --- src/components/legend/draw.js | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index c7b47a2ce1f..1f7f0987154 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -368,7 +368,6 @@ function drawTexts(context, gd, d, i, traces) { function repositionLegend(gd, traces) { var fullLayout = gd._fullLayout, - gs = fullLayout._size, opts = fullLayout.legend, borderwidth = opts.borderwidth; @@ -432,39 +431,27 @@ function repositionLegend(gd, traces) { .attr('width', (gd._context.editable ? 0 : opts.width) + 40); // now position the legend. for both x,y the positions are recorded as - // fractions of the plot area (left, bottom = 0,0). Outside the plot - // area is allowed but position will be clipped to the page. - // values <1/3 align the low side at that fraction, 1/3-2/3 align the - // center at that fraction, >2/3 align the right at that fraction - - var lx = gs.l + gs.w * opts.x, - ly = gs.t + gs.h * (1-opts.y); + // fractions of the plot area (left, bottom = 0,0). var xanchor = 'left'; if(anchorUtils.isRightAnchor(opts)) { - lx -= opts.width; xanchor = 'right'; } if(anchorUtils.isCenterAnchor(opts)) { - lx -= opts.width / 2; xanchor = 'center'; } var yanchor = 'top'; if(anchorUtils.isBottomAnchor(opts)) { - ly -= opts.height; yanchor = 'bottom'; } if(anchorUtils.isMiddleAnchor(opts)) { - ly -= opts.height / 2; yanchor = 'middle'; } // make sure we're only getting full pixels opts.width = Math.ceil(opts.width); opts.height = Math.ceil(opts.height); - lx = Math.round(lx); - ly = Math.round(ly); // lastly check if the margin auto-expand has changed Plots.autoMargin(gd, 'legend', { From c68ed58d95b3949a90c8efa00ee413434d271976 Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Mon, 11 Apr 2016 10:00:23 +0100 Subject: [PATCH 02/12] Legend.draw: Add missing `select('rect')` --- src/components/legend/draw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 1f7f0987154..3ca247f63b7 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -227,7 +227,7 @@ module.exports = function draw(gd) { width: opts.width - 2 * opts.borderwidth + constants.scrollBarWidth }); - clipPath.attr({ + clipPath.select('rect').attr({ width: opts.width + constants.scrollBarWidth }); From 91c7757c020bd157b852d96d003cf265d3ead16f Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Sat, 9 Apr 2016 12:06:17 +0100 Subject: [PATCH 03/12] Fix invisible legends with negative y Fixes #384 --- src/components/legend/draw.js | 54 +++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 3ca247f63b7..efff9580904 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -184,27 +184,51 @@ module.exports = function draw(gd) { if(anchorUtils.isRightAnchor(opts)) { lx -= opts.width; } - if(anchorUtils.isCenterAnchor(opts)) { + else if(anchorUtils.isCenterAnchor(opts)) { lx -= opts.width / 2; } if(anchorUtils.isBottomAnchor(opts)) { ly -= opts.height; } - if(anchorUtils.isMiddleAnchor(opts)) { + else if(anchorUtils.isMiddleAnchor(opts)) { ly -= opts.height / 2; } + lx = Math.round(lx); + ly = Math.round(ly); + + // Make sure the legend top and bottom are visible + // (legends with a scroll bar are not allowed to stretch beyond the extended + // margins) + var lyMin = 0; + var lyMax = fullLayout.margin.t + fullLayout.height + fullLayout.margin.b; + var legendHeight = opts.height; + var legendHeightMax = gs.h; + + + if(legendHeight > legendHeightMax) { + ly = gs.t; + legendHeight = legendHeightMax; + } + else { + if(ly > lyMax) ly = lyMax - legendHeight; + + if(ly < lyMin) ly = lyMin; + + legendHeight = Math.min(lyMax - ly, opts.height); + } + // Deal with scrolling - var plotHeight = fullLayout.height - fullLayout.margin.b, - scrollheight = Math.min(plotHeight - ly, opts.height), - scrollPosition = scrollBox.attr('data-scroll') ? scrollBox.attr('data-scroll') : 0; + var scrollPosition = scrollBox.attr('data-scroll') ? + scrollBox.attr('data-scroll') : + 0; scrollBox.attr('transform', 'translate(0, ' + scrollPosition + ')'); bg.attr({ width: opts.width - 2 * opts.borderwidth, - height: scrollheight - 2 * opts.borderwidth, + height: legendHeight - 2 * opts.borderwidth, x: opts.borderwidth, y: opts.borderwidth }); @@ -213,7 +237,7 @@ module.exports = function draw(gd) { clipPath.select('rect').attr({ width: opts.width, - height: scrollheight, + height: legendHeight, x: 0, y: 0 }); @@ -221,7 +245,7 @@ module.exports = function draw(gd) { legend.call(Drawing.setClipUrl, clipId); // If scrollbar should be shown. - if(opts.height - scrollheight > 0 && !gd._context.staticPlot) { + if(opts.height - legendHeight > 0 && !gd._context.staticPlot) { bg.attr({ width: opts.width - 2 * opts.borderwidth + constants.scrollBarWidth @@ -243,21 +267,21 @@ module.exports = function draw(gd) { scrollBox.attr('data-scroll',0); } - scrollHandler(0,scrollheight); + scrollHandler(0,legendHeight); legend.on('wheel',null); legend.on('wheel', function() { var e = d3.event; e.preventDefault(); - scrollHandler(e.deltaY / 20, scrollheight); + scrollHandler(e.deltaY / 20, legendHeight); }); scrollBar.on('.drag',null); scrollBox.on('.drag',null); var drag = d3.behavior.drag() .on('drag', function() { - scrollHandler(d3.event.dy, scrollheight); + scrollHandler(d3.event.dy, legendHeight); }); scrollBar.call(drag); @@ -266,12 +290,12 @@ module.exports = function draw(gd) { } - function scrollHandler(delta, scrollheight) { + function scrollHandler(delta, legendHeight) { - var scrollBarTrack = scrollheight - constants.scrollBarHeight - 2 * constants.scrollBarMargin, + var scrollBarTrack = legendHeight - constants.scrollBarHeight - 2 * constants.scrollBarMargin, translateY = scrollBox.attr('data-scroll'), - scrollBoxY = Lib.constrain(translateY - delta, scrollheight-opts.height, 0), - scrollBarY = -scrollBoxY / (opts.height - scrollheight) * scrollBarTrack + constants.scrollBarMargin; + scrollBoxY = Lib.constrain(translateY - delta, legendHeight-opts.height, 0), + scrollBarY = -scrollBoxY / (opts.height - legendHeight) * scrollBarTrack + constants.scrollBarMargin; scrollBox.attr('data-scroll', scrollBoxY); scrollBox.attr('transform', 'translate(0, ' + scrollBoxY + ')'); From cedabd385c8043449e33d45504983dba4d87a87a Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Mon, 11 Apr 2016 12:00:16 +0100 Subject: [PATCH 04/12] Do not round off the legend location * Commented out the statements to round off the legend location, in order to reproduce the baseline images. --- src/components/legend/draw.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index efff9580904..62465809f46 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -195,8 +195,8 @@ module.exports = function draw(gd) { ly -= opts.height / 2; } - lx = Math.round(lx); - ly = Math.round(ly); + //lx = Math.round(lx); + //ly = Math.round(ly); // Make sure the legend top and bottom are visible // (legends with a scroll bar are not allowed to stretch beyond the extended From 7f71b531489fd42bf9bffd10ff35ee04220d2a47 Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Tue, 12 Apr 2016 21:47:15 +0100 Subject: [PATCH 05/12] Fix computation of lowest possible legend position --- src/components/legend/draw.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 62465809f46..1e9a66ecc85 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -201,10 +201,10 @@ module.exports = function draw(gd) { // Make sure the legend top and bottom are visible // (legends with a scroll bar are not allowed to stretch beyond the extended // margins) - var lyMin = 0; - var lyMax = fullLayout.margin.t + fullLayout.height + fullLayout.margin.b; - var legendHeight = opts.height; - var legendHeightMax = gs.h; + var lyMin = 0, + lyMax = fullLayout.height, + legendHeight = opts.height, + legendHeightMax = gs.h; if(legendHeight > legendHeightMax) { @@ -220,9 +220,7 @@ module.exports = function draw(gd) { } // Deal with scrolling - var scrollPosition = scrollBox.attr('data-scroll') ? - scrollBox.attr('data-scroll') : - 0; + var scrollPosition = scrollBox.attr('data-scroll') || 0; scrollBox.attr('transform', 'translate(0, ' + scrollPosition + ')'); From b74722405d27a3df145092865a719ebef0469225 Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Tue, 12 Apr 2016 22:13:18 +0100 Subject: [PATCH 06/12] Fix position of legend scrollbar --- src/components/legend/draw.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 1e9a66ecc85..c28f9f5f68b 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -257,7 +257,7 @@ module.exports = function draw(gd) { // Move scrollbar to starting position scrollBar.call( Drawing.setRect, - opts.width - (constants.scrollBarWidth + constants.scrollBarMargin), + opts.width - constants.scrollBarMargin, constants.scrollBarMargin, constants.scrollBarWidth, constants.scrollBarHeight @@ -299,7 +299,7 @@ module.exports = function draw(gd) { scrollBox.attr('transform', 'translate(0, ' + scrollBoxY + ')'); scrollBar.call( Drawing.setRect, - opts.width - (constants.scrollBarWidth + constants.scrollBarMargin), + opts.width - constants.scrollBarMargin, scrollBarY, constants.scrollBarWidth, constants.scrollBarHeight From 8baac4712616357de7390a8b17d825022d732142 Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Wed, 13 Apr 2016 10:30:01 +0100 Subject: [PATCH 07/12] Don't expand vertical margin if legend doesn't fit --- src/components/legend/draw.js | 69 ++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index c28f9f5f68b..0be36f35575 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -172,7 +172,18 @@ module.exports = function draw(gd) { }); // Position and size the legend - repositionLegend(gd, traces); + var lyMin = 0, + lyMax = fullLayout.height; + + computeLegendDimensions(gd, traces); + + if(opts.height > lyMax) { + // If the legend doesn't fit in the plot area, + // do not expand the vertical margins. + expandHorizontalMargin(gd); + } else { + expandMargin(gd); + } // Scroll section must be executed after repositionLegend. // It requires the legend width, height, x and y to position the scrollbox @@ -201,21 +212,16 @@ module.exports = function draw(gd) { // Make sure the legend top and bottom are visible // (legends with a scroll bar are not allowed to stretch beyond the extended // margins) - var lyMin = 0, - lyMax = fullLayout.height, - legendHeight = opts.height, + var legendHeight = opts.height, legendHeightMax = gs.h; - if(legendHeight > legendHeightMax) { ly = gs.t; legendHeight = legendHeightMax; } else { if(ly > lyMax) ly = lyMax - legendHeight; - if(ly < lyMin) ly = lyMin; - legendHeight = Math.min(lyMax - ly, opts.height); } @@ -369,7 +375,10 @@ function drawTexts(context, gd, d, i, traces) { function textLayout(s) { Plotly.util.convertToTspans(s, function() { - if(gd.firstRender) repositionLegend(gd, traces); + if(gd.firstRender) { + computeLegendDimensions(gd, traces); + expandMargin(gd); + } }); s.selectAll('tspan.line').attr({x: s.attr('x')}); } @@ -388,7 +397,7 @@ function drawTexts(context, gd, d, i, traces) { else text.call(textLayout); } -function repositionLegend(gd, traces) { +function computeLegendDimensions(gd, traces) { var fullLayout = gd._fullLayout, opts = fullLayout.legend, borderwidth = opts.borderwidth; @@ -441,7 +450,6 @@ function repositionLegend(gd, traces) { opts.width = Math.max(opts.width, tWidth || 0); }); - opts.width += 45 + borderwidth * 2; opts.height += 10 + borderwidth * 2; @@ -452,14 +460,20 @@ function repositionLegend(gd, traces) { traces.selectAll('.legendtoggle') .attr('width', (gd._context.editable ? 0 : opts.width) + 40); - // now position the legend. for both x,y the positions are recorded as - // fractions of the plot area (left, bottom = 0,0). + // make sure we're only getting full pixels + opts.width = Math.ceil(opts.width); + opts.height = Math.ceil(opts.height); +} + +function expandMargin(gd) { + var fullLayout = gd._fullLayout, + opts = fullLayout.legend; var xanchor = 'left'; if(anchorUtils.isRightAnchor(opts)) { xanchor = 'right'; } - if(anchorUtils.isCenterAnchor(opts)) { + else if(anchorUtils.isCenterAnchor(opts)) { xanchor = 'center'; } @@ -467,14 +481,10 @@ function repositionLegend(gd, traces) { if(anchorUtils.isBottomAnchor(opts)) { yanchor = 'bottom'; } - if(anchorUtils.isMiddleAnchor(opts)) { + else if(anchorUtils.isMiddleAnchor(opts)) { yanchor = 'middle'; } - // make sure we're only getting full pixels - opts.width = Math.ceil(opts.width); - opts.height = Math.ceil(opts.height); - // lastly check if the margin auto-expand has changed Plots.autoMargin(gd, 'legend', { x: opts.x, @@ -485,3 +495,26 @@ function repositionLegend(gd, traces) { t: opts.height * ({bottom: 1, middle: 0.5}[yanchor] || 0) }); } + +function expandHorizontalMargin(gd) { + var fullLayout = gd._fullLayout, + opts = fullLayout.legend; + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(opts)) { + xanchor = 'right'; + } + else if(anchorUtils.isCenterAnchor(opts)) { + xanchor = 'center'; + } + + // lastly check if the margin auto-expand has changed + Plots.autoMargin(gd, 'legend', { + x: opts.x, + y: 0.5, + l: opts.width * ({right: 1, center: 0.5}[xanchor] || 0), + r: opts.width * ({left: 1, center: 0.5}[xanchor] || 0), + b: 0, + t: 0 + }); +} From c96581cbd7b323cc8ccf678515573b399ddcb34a Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Wed, 13 Apr 2016 10:48:38 +0100 Subject: [PATCH 08/12] Improve drag and wheel of legend scrollbars * Now drag events make the scrollbar follow the mouse position. * Now wheel events move the scrollbar position as fast as drag events. --- src/components/legend/draw.js | 42 ++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 0be36f35575..3bfe4586a63 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -271,22 +271,38 @@ module.exports = function draw(gd) { scrollBox.attr('data-scroll',0); } - scrollHandler(0,legendHeight); + var scrollBarYMax = legendHeight - + constants.scrollBarHeight - + 2 * constants.scrollBarMargin, + scrollBoxYMax = opts.height - legendHeight, + scrollBarY = constants.scrollBarMargin, + scrollBoxY = 0; - legend.on('wheel',null); + scrollHandler(scrollBarY, scrollBoxY); + legend.on('wheel',null); legend.on('wheel', function() { - var e = d3.event; - e.preventDefault(); - scrollHandler(e.deltaY / 20, legendHeight); + scrollBoxY = Lib.constrain( + scrollBox.attr('data-scroll') - + d3.event.deltaY / scrollBarYMax * scrollBoxYMax, + -scrollBoxYMax, 0); + scrollBarY = constants.scrollBarMargin - + scrollBoxY / scrollBoxYMax * scrollBarYMax; + scrollHandler(scrollBarY, scrollBoxY); + d3.event.preventDefault(); }); scrollBar.on('.drag',null); scrollBox.on('.drag',null); - var drag = d3.behavior.drag() - .on('drag', function() { - scrollHandler(d3.event.dy, legendHeight); - }); + var drag = d3.behavior.drag().on('drag', function() { + scrollBarY = Lib.constrain( + d3.event.y - constants.scrollBarHeight / 2, + constants.scrollBarMargin, + constants.scrollBarMargin + scrollBarYMax); + scrollBoxY = - (scrollBarY - constants.scrollBarMargin) / + scrollBarYMax * scrollBoxYMax; + scrollHandler(scrollBarY, scrollBoxY); + }); scrollBar.call(drag); scrollBox.call(drag); @@ -294,13 +310,7 @@ module.exports = function draw(gd) { } - function scrollHandler(delta, legendHeight) { - - var scrollBarTrack = legendHeight - constants.scrollBarHeight - 2 * constants.scrollBarMargin, - translateY = scrollBox.attr('data-scroll'), - scrollBoxY = Lib.constrain(translateY - delta, legendHeight-opts.height, 0), - scrollBarY = -scrollBoxY / (opts.height - legendHeight) * scrollBarTrack + constants.scrollBarMargin; - + function scrollHandler(scrollBarY, scrollBoxY) { scrollBox.attr('data-scroll', scrollBoxY); scrollBox.attr('transform', 'translate(0, ' + scrollBoxY + ')'); scrollBar.call( From a05080de3db1b06c486380f6e998c8eecd1fc94e Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Wed, 13 Apr 2016 13:30:29 +0100 Subject: [PATCH 09/12] Update legend mouse wheel test --- test/jasmine/tests/legend_scroll_test.js | 26 ++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/test/jasmine/tests/legend_scroll_test.js b/test/jasmine/tests/legend_scroll_test.js index e7bdacdf7a3..a7c4f28772f 100644 --- a/test/jasmine/tests/legend_scroll_test.js +++ b/test/jasmine/tests/legend_scroll_test.js @@ -1,5 +1,6 @@ var Plotly = require('@lib/index'); var Lib = require('@src/lib'); +var constants = require('@src/components/legend/constants'); var createGraph = require('../assets/create_graph_div'); var destroyGraph = require('../assets/destroy_graph_div'); @@ -55,14 +56,23 @@ describe('The legend', function() { }); it('should scroll when there\'s a wheel event', function() { - var scrollBox = legend.getElementsByClassName('scrollbox')[0]; - - legend.dispatchEvent(scrollTo(100)); - - // Compare against -5 because of a scroll factor of 20 - // ( 100 / 20 === 5 ) - expect(scrollBox.getAttribute('transform')).toBe('translate(0, -5)'); - expect(scrollBox.getAttribute('data-scroll')).toBe('-5'); + var scrollBox = legend.getElementsByClassName('scrollbox')[0], + legendHeight = getBBox(legend).height, + scrollBoxYMax = gd._fullLayout.legend.height - legendHeight, + scrollBarYMax = legendHeight - + constants.scrollBarHeight - + 2 * constants.scrollBarMargin, + initialDataScroll = scrollBox.getAttribute('data-scroll'), + wheelDeltaY = 100, + finalDataScroll = '' + Lib.constrain(initialDataScroll - + wheelDeltaY / scrollBarYMax * scrollBoxYMax, + -scrollBoxYMax, 0); + + legend.dispatchEvent(scrollTo(wheelDeltaY)); + + expect(scrollBox.getAttribute('data-scroll')).toBe(finalDataScroll); + expect(scrollBox.getAttribute('transform')).toBe( + 'translate(0, ' + finalDataScroll + ')'); }); it('should constrain scrolling to the contents', function() { From e1effce2822c26bef0a8bc9ff0990391a41b46d9 Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Thu, 14 Apr 2016 01:12:30 +0100 Subject: [PATCH 10/12] Honour the scrollbar margin --- src/components/legend/draw.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 3bfe4586a63..47a26fbb8af 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -251,24 +251,24 @@ module.exports = function draw(gd) { // If scrollbar should be shown. if(opts.height - legendHeight > 0 && !gd._context.staticPlot) { + // increase the background and clip-path width + // by the scrollbar width and margin bg.attr({ - width: opts.width - 2 * opts.borderwidth + constants.scrollBarWidth + width: opts.width - + 2 * opts.borderwidth + + constants.scrollBarWidth + + constants.scrollBarMargin }); clipPath.select('rect').attr({ - width: opts.width + constants.scrollBarWidth + width: opts.width + + constants.scrollBarWidth + + constants.scrollBarMargin }); if(gd.firstRender) { // Move scrollbar to starting position - scrollBar.call( - Drawing.setRect, - opts.width - constants.scrollBarMargin, - constants.scrollBarMargin, - constants.scrollBarWidth, - constants.scrollBarHeight - ); - scrollBox.attr('data-scroll',0); + scrollHandler(constants.scrollBarMargin, 0); } var scrollBarYMax = legendHeight - @@ -315,7 +315,7 @@ module.exports = function draw(gd) { scrollBox.attr('transform', 'translate(0, ' + scrollBoxY + ')'); scrollBar.call( Drawing.setRect, - opts.width - constants.scrollBarMargin, + opts.width, scrollBarY, constants.scrollBarWidth, constants.scrollBarHeight From c581989c6656ca50e930230aeaeaaa8a7d965093 Mon Sep 17 00:00:00 2001 From: Nicolas Riesco Date: Thu, 14 Apr 2016 13:28:35 +0100 Subject: [PATCH 11/12] Add mock with a legend located at y -1 --- test/image/baselines/legend_negative_y.png | Bin 0 -> 21788 bytes test/image/mocks/legend_negative_y.json | 62 +++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 test/image/baselines/legend_negative_y.png create mode 100644 test/image/mocks/legend_negative_y.json diff --git a/test/image/baselines/legend_negative_y.png b/test/image/baselines/legend_negative_y.png new file mode 100644 index 0000000000000000000000000000000000000000..de930a6459d275fe614056fbc5a69e66401825a4 GIT binary patch literal 21788 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 Date: Thu, 14 Apr 2016 16:36:44 +0100 Subject: [PATCH 12/12] Remove commented-out lines from Legend.draw() --- src/components/legend/draw.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 47a26fbb8af..6bc75928327 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -206,9 +206,6 @@ module.exports = function draw(gd) { ly -= opts.height / 2; } - //lx = Math.round(lx); - //ly = Math.round(ly); - // Make sure the legend top and bottom are visible // (legends with a scroll bar are not allowed to stretch beyond the extended // margins)