From 60b0936c303f2442578c2f481c829b3093df5009 Mon Sep 17 00:00:00 2001 From: Shumpei Shiina Date: Wed, 14 Oct 2020 23:09:41 +0900 Subject: [PATCH 1/2] add legend.itemwidth option to set the width of the symbol area of legends --- src/components/legend/attributes.js | 7 +++ src/components/legend/constants.js | 2 - src/components/legend/defaults.js | 1 + src/components/legend/draw.js | 8 ++-- src/components/legend/style.js | 26 +++++----- .../baselines/legend_itemwidth_dashline.png | Bin 0 -> 27667 bytes .../mocks/legend_itemwidth_dashline.json | 45 ++++++++++++++++++ test/jasmine/tests/mock_test.js | 2 + 8 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 test/image/baselines/legend_itemwidth_dashline.png create mode 100644 test/image/mocks/legend_itemwidth_dashline.json diff --git a/src/components/legend/attributes.js b/src/components/legend/attributes.js index 8e2456ef157..d478d39c5b3 100644 --- a/src/components/legend/attributes.js +++ b/src/components/legend/attributes.js @@ -92,6 +92,13 @@ module.exports = { 'or remain *constant* independent of the symbol size on the graph.' ].join(' ') }, + itemwidth: { + valType: 'number', + dflt: 30, + role: 'style', + editType: 'legend', + description: 'Sets the width (in px) of the legend item symbols (the part other than the text).', + }, itemclick: { valType: 'enumerated', diff --git a/src/components/legend/constants.js b/src/components/legend/constants.js index 67a0468c3d2..8a213bf6413 100644 --- a/src/components/legend/constants.js +++ b/src/components/legend/constants.js @@ -17,8 +17,6 @@ module.exports = { // number of px between legend title and (left) side of legend (always in x direction and from inner border) titlePad: 2, - // number of px between legend symbol and legend text (always in x direction) - textGap: 40, // number of px between each legend item (x and/or y direction) itemGap: 5 }; diff --git a/src/components/legend/defaults.js b/src/components/legend/defaults.js index 9077a1e7890..06e2bce6d12 100644 --- a/src/components/legend/defaults.js +++ b/src/components/legend/defaults.js @@ -113,6 +113,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { if(helpers.isGrouped(layoutOut.legend)) coerce('tracegroupgap'); coerce('itemsizing'); + coerce('itemwidth'); coerce('itemclick'); coerce('itemdoubleclick'); diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js index 945067b5a40..4f79e30c5b9 100644 --- a/src/components/legend/draw.js +++ b/src/components/legend/draw.js @@ -412,7 +412,8 @@ function drawTexts(g, gd, opts) { .call(Drawing.font, opts.font) .text(isEditable ? ensureLength(name, maxNameLength) : name); - svgTextUtils.positionText(textEl, constants.textGap, 0); + var textGap = opts.itemwidth + constants.itemGap * 2; + svgTextUtils.positionText(textEl, textGap, 0); if(isEditable) { textEl.call(svgTextUtils.makeEditable, {gd: gd, text: name}) @@ -539,7 +540,8 @@ function computeTextDimensions(g, gd, opts) { // to avoid getBoundingClientRect var textY = lineHeight * ((textLines - 1) / 2 - 0.3); if(legendItem) { - svgTextUtils.positionText(textEl, constants.textGap, -textY); + var textGap = opts.itemwidth + constants.itemGap * 2; + svgTextUtils.positionText(textEl, textGap, -textY); } else { // case of title svgTextUtils.positionText(textEl, constants.titlePad + bw, lineHeight + bw); } @@ -592,8 +594,8 @@ function computeLegendDimensions(gd, groups, traces, opts) { var bw = opts.borderwidth; var bw2 = 2 * bw; - var textGap = constants.textGap; var itemGap = constants.itemGap; + var textGap = opts.itemwidth + itemGap * 2; var endPad = 2 * (bw + itemGap); var yanchor = getYanchor(opts); diff --git a/src/components/legend/style.js b/src/components/legend/style.js index b7b9bec7618..5cf8e451092 100644 --- a/src/components/legend/style.js +++ b/src/components/legend/style.js @@ -20,6 +20,8 @@ var subTypes = require('../../traces/scatter/subtypes'); var stylePie = require('../../traces/pie/style_one'); var pieCastOption = require('../../traces/pie/helpers').castOption; +var constants = require('./constants'); + var CST_MARKER_SIZE = 12; var CST_LINE_WIDTH = 5; var CST_MARKER_LINE_WIDTH = 2; @@ -30,6 +32,8 @@ module.exports = function style(s, gd, legend) { var fullLayout = gd._fullLayout; if(!legend) legend = fullLayout.legend; var constantItemSizing = legend.itemsizing === 'constant'; + var itemWidth = legend.itemwidth; + var centerPos = (itemWidth + constants.itemGap * 2) / 2; var boundLineWidth = function(mlw, cont, max, cst) { var v; @@ -161,7 +165,7 @@ module.exports = function style(s, gd, legend) { .data(showFill || showGradientFill ? [d] : []); fill.enter().append('path').classed('js-fill', true); fill.exit().remove(); - fill.attr('d', pathStart + 'h30v6h-30z') + fill.attr('d', pathStart + 'h' + itemWidth + 'v6h-' + itemWidth + 'z') .call(showFill ? Drawing.fillGroupStyle : fillGradient); if(showLine || showGradientLine) { @@ -181,7 +185,7 @@ module.exports = function style(s, gd, legend) { // though there *is* no vertical variation in this case. // so add an invisibly small angle to the line // This issue (and workaround) exist across (Mac) Chrome, FF, and Safari - line.attr('d', pathStart + (showGradientLine ? 'l30,0.0001' : 'h30')) + line.attr('d', pathStart + (showGradientLine ? 'l' + itemWidth + ',0.0001' : 'h' + itemWidth)) .call(showLine ? Drawing.lineGroupStyle : lineGradient); } @@ -271,7 +275,7 @@ module.exports = function style(s, gd, legend) { // make sure marker is on the bottom, in case it enters after text pts.enter().insert('path', ':first-child') .classed('scatterpts', true) - .attr('transform', 'translate(20,0)'); + .attr('transform', 'translate(' + centerPos + ',0)'); pts.exit().remove(); pts.call(Drawing.pointStyle, tMod, gd); @@ -283,7 +287,7 @@ module.exports = function style(s, gd, legend) { .data(showText ? dMod : []); txt.enter() .append('g').classed('pointtext', true) - .append('text').attr('transform', 'translate(20,0)'); + .append('text').attr('transform', 'translate(' + centerPos + ',0)'); txt.exit().remove(); txt.selectAll('text').call(Drawing.textPointStyle, tMod, gd); } @@ -311,7 +315,7 @@ module.exports = function style(s, gd, legend) { .selectAll('path.legendwaterfall') .data(ptsData); pts.enter().append('path').classed('legendwaterfall', true) - .attr('transform', 'translate(20,0)') + .attr('transform', 'translate(' + centerPos + ',0)') .style('stroke-miterlimit', 1); pts.exit().remove(); @@ -351,7 +355,7 @@ module.exports = function style(s, gd, legend) { .data(isVisible ? [d] : []); barpath.enter().append('path').classed('legend' + desiredType, true) .attr('d', 'M6,6H-6V-6H6Z') - .attr('transform', 'translate(20,0)'); + .attr('transform', 'translate(' + centerPos + ',0)'); barpath.exit().remove(); barpath.each(function(d) { @@ -375,7 +379,7 @@ module.exports = function style(s, gd, legend) { pts.enter().append('path').classed('legendbox', true) // if we want the median bar, prepend M6,0H-6 .attr('d', 'M6,6H-6V-6H6Z') - .attr('transform', 'translate(20,0)'); + .attr('transform', 'translate(' + centerPos + ',0)'); pts.exit().remove(); pts.each(function() { @@ -415,7 +419,7 @@ module.exports = function style(s, gd, legend) { if(i) return 'M-15,0H-8M-8,6V-6H8Z'; // increasing return 'M15,0H8M8,-6V6H-8Z'; // decreasing }) - .attr('transform', 'translate(20,0)') + .attr('transform', 'translate(' + centerPos + ',0)') .style('stroke-miterlimit', 1); pts.exit().remove(); @@ -442,7 +446,7 @@ module.exports = function style(s, gd, legend) { if(i) return 'M-15,0H0M-8,-6V0'; // increasing return 'M15,0H0M8,6V0'; // decreasing }) - .attr('transform', 'translate(20,0)') + .attr('transform', 'translate(' + centerPos + ',0)') .style('stroke-miterlimit', 1); pts.exit().remove(); @@ -478,7 +482,7 @@ module.exports = function style(s, gd, legend) { .data(isVisible ? [d] : []); pts.enter().append('path').classed('legend' + desiredType, true) .attr('d', 'M6,6H-6V-6H6Z') - .attr('transform', 'translate(20,0)'); + .attr('transform', 'translate(' + centerPos + ',0)'); pts.exit().remove(); if(pts.size()) { @@ -576,7 +580,7 @@ module.exports = function style(s, gd, legend) { .selectAll('path.legend3dandfriends') .data(ptsData); pts.enter().append('path').classed('legend3dandfriends', true) - .attr('transform', 'translate(20,0)') + .attr('transform', 'translate(' + centerPos + ',0)') .style('stroke-miterlimit', 1); pts.exit().remove(); diff --git a/test/image/baselines/legend_itemwidth_dashline.png b/test/image/baselines/legend_itemwidth_dashline.png new file mode 100644 index 0000000000000000000000000000000000000000..016e4aaa4d2d4dfb940b8ac9153f735af9e08b20 GIT binary patch literal 27667 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 Date: Wed, 4 Nov 2020 09:17:18 +0900 Subject: [PATCH 2/2] Fix based on review comments --- src/components/legend/attributes.js | 3 ++- src/components/legend/style.js | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/components/legend/attributes.js b/src/components/legend/attributes.js index d478d39c5b3..07e4785fbe9 100644 --- a/src/components/legend/attributes.js +++ b/src/components/legend/attributes.js @@ -94,10 +94,11 @@ module.exports = { }, itemwidth: { valType: 'number', + min: 30, dflt: 30, role: 'style', editType: 'legend', - description: 'Sets the width (in px) of the legend item symbols (the part other than the text).', + description: 'Sets the width (in px) of the legend item symbols (the part other than the title.text).', }, itemclick: { diff --git a/src/components/legend/style.js b/src/components/legend/style.js index 5cf8e451092..e34143cafe9 100644 --- a/src/components/legend/style.js +++ b/src/components/legend/style.js @@ -34,6 +34,7 @@ module.exports = function style(s, gd, legend) { var constantItemSizing = legend.itemsizing === 'constant'; var itemWidth = legend.itemwidth; var centerPos = (itemWidth + constants.itemGap * 2) / 2; + var centerTransform = 'translate(' + centerPos + ',0)'; var boundLineWidth = function(mlw, cont, max, cst) { var v; @@ -275,7 +276,7 @@ module.exports = function style(s, gd, legend) { // make sure marker is on the bottom, in case it enters after text pts.enter().insert('path', ':first-child') .classed('scatterpts', true) - .attr('transform', 'translate(' + centerPos + ',0)'); + .attr('transform', centerTransform); pts.exit().remove(); pts.call(Drawing.pointStyle, tMod, gd); @@ -287,7 +288,7 @@ module.exports = function style(s, gd, legend) { .data(showText ? dMod : []); txt.enter() .append('g').classed('pointtext', true) - .append('text').attr('transform', 'translate(' + centerPos + ',0)'); + .append('text').attr('transform', centerTransform); txt.exit().remove(); txt.selectAll('text').call(Drawing.textPointStyle, tMod, gd); } @@ -315,7 +316,7 @@ module.exports = function style(s, gd, legend) { .selectAll('path.legendwaterfall') .data(ptsData); pts.enter().append('path').classed('legendwaterfall', true) - .attr('transform', 'translate(' + centerPos + ',0)') + .attr('transform', centerTransform) .style('stroke-miterlimit', 1); pts.exit().remove(); @@ -355,7 +356,7 @@ module.exports = function style(s, gd, legend) { .data(isVisible ? [d] : []); barpath.enter().append('path').classed('legend' + desiredType, true) .attr('d', 'M6,6H-6V-6H6Z') - .attr('transform', 'translate(' + centerPos + ',0)'); + .attr('transform', centerTransform); barpath.exit().remove(); barpath.each(function(d) { @@ -379,7 +380,7 @@ module.exports = function style(s, gd, legend) { pts.enter().append('path').classed('legendbox', true) // if we want the median bar, prepend M6,0H-6 .attr('d', 'M6,6H-6V-6H6Z') - .attr('transform', 'translate(' + centerPos + ',0)'); + .attr('transform', centerTransform); pts.exit().remove(); pts.each(function() { @@ -419,7 +420,7 @@ module.exports = function style(s, gd, legend) { if(i) return 'M-15,0H-8M-8,6V-6H8Z'; // increasing return 'M15,0H8M8,-6V6H-8Z'; // decreasing }) - .attr('transform', 'translate(' + centerPos + ',0)') + .attr('transform', centerTransform) .style('stroke-miterlimit', 1); pts.exit().remove(); @@ -446,7 +447,7 @@ module.exports = function style(s, gd, legend) { if(i) return 'M-15,0H0M-8,-6V0'; // increasing return 'M15,0H0M8,6V0'; // decreasing }) - .attr('transform', 'translate(' + centerPos + ',0)') + .attr('transform', centerTransform) .style('stroke-miterlimit', 1); pts.exit().remove(); @@ -482,7 +483,7 @@ module.exports = function style(s, gd, legend) { .data(isVisible ? [d] : []); pts.enter().append('path').classed('legend' + desiredType, true) .attr('d', 'M6,6H-6V-6H6Z') - .attr('transform', 'translate(' + centerPos + ',0)'); + .attr('transform', centerTransform); pts.exit().remove(); if(pts.size()) { @@ -580,7 +581,7 @@ module.exports = function style(s, gd, legend) { .selectAll('path.legend3dandfriends') .data(ptsData); pts.enter().append('path').classed('legend3dandfriends', true) - .attr('transform', 'translate(' + centerPos + ',0)') + .attr('transform', centerTransform) .style('stroke-miterlimit', 1); pts.exit().remove();