diff --git a/draftlogs/7908_fix.md b/draftlogs/7908_fix.md new file mode 100644 index 00000000000..955c79cea16 --- /dev/null +++ b/draftlogs/7908_fix.md @@ -0,0 +1 @@ + - Fix crash ("Something went wrong with axis scaling") when a colorbar's title or padding leaves it with a negative domain length [[#7908](https://github.com/plotly/plotly.js/pull/7908)] diff --git a/src/components/colorbar/draw.js b/src/components/colorbar/draw.js index 3fe5a5e9ce3..5fbf919d3ae 100644 --- a/src/components/colorbar/draw.js +++ b/src/components/colorbar/draw.js @@ -167,6 +167,12 @@ function makeColorBarData(gd) { return out; } +// Move domain[0] toward domain[1] by delta, without crossing it +const insetDomainStart = (domain, delta) => [Math.min(domain[0] + delta, domain[1]), domain[1]]; + +// Move domain[1] toward domain[0] by delta, without crossing it +const insetDomainEnd = (domain, delta) => [domain[0], Math.max(domain[1] - delta, domain[0])]; + function drawColorBar(g, opts, gd) { var isVertical = opts.orientation === 'v'; var len = opts.len; @@ -300,13 +306,8 @@ function drawColorBar(g, opts, gd) { // set domain after init, because we may want to // allow it outside [0,1] - ax.domain = isVertical ? [ - vFrac + ypad / gs.h, - vFrac + lenFrac - ypad / gs.h - ] : [ - vFrac + xpad / gs.w, - vFrac + lenFrac - xpad / gs.w - ]; + var padFrac = isVertical ? ypad / gs.h : xpad / gs.w; + ax.domain = insetDomainEnd(insetDomainStart([vFrac, vFrac + lenFrac], padFrac), padFrac); ax.setScale(); @@ -473,10 +474,10 @@ function drawColorBar(g, opts, gd) { titleHeight += 5; if(titleSide === 'top') { - ax.domain[1] -= titleHeight / gs.h; + ax.domain = insetDomainEnd(ax.domain, titleHeight / gs.h); titleTrans[1] *= -1; } else { - ax.domain[0] += titleHeight / gs.h; + ax.domain = insetDomainStart(ax.domain, titleHeight / gs.h); var nlines = svgTextUtils.lineCount(titleText); titleTrans[1] += (1 - nlines) * lineSize; } @@ -487,7 +488,7 @@ function drawColorBar(g, opts, gd) { } else { // horizontal colorbars if(titleWidth) { if(titleSide === 'right') { - ax.domain[0] += (titleWidth + titleFontSize / 2) / gs.w; + ax.domain = insetDomainStart(ax.domain, (titleWidth + titleFontSize / 2) / gs.w); } titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1])); diff --git a/test/jasmine/tests/colorbar_test.js b/test/jasmine/tests/colorbar_test.js index 99fa90e5e5b..1785f8cb21c 100644 --- a/test/jasmine/tests/colorbar_test.js +++ b/test/jasmine/tests/colorbar_test.js @@ -95,6 +95,76 @@ describe('Test colorbar:', function() { .then(done, done.fail); }); + // see https://github.com/plotly/plotly.js/issues/6499 + it('does not throw when the colorbar is too short for its own length/padding', function(done) { + Plotly.newPlot(gd, [{ + type: 'scatter', + mode: 'markers', + x: [1, 2, 3], + y: [1, 2, 3], + marker: { + color: [1, 2, 3], + colorbar: {len: 0.01, thickness: 30} + } + }], {width: 300, height: 120}) + .then(done, done.fail); + }); + + it('does not throw when a top-side colorbar title is taller than the colorbar', function(done) { + Plotly.newPlot(gd, [{ + type: 'scatter', + mode: 'markers', + x: [1, 2, 3], + y: [1, 2, 3], + marker: { + color: [1, 2, 3], + colorbar: { + title: {text: 'Long title', side: 'top', font: {size: 60}}, + len: 0.3, + thickness: 30 + } + } + }], {width: 300, height: 120}) + .then(done, done.fail); + }); + + it('does not throw when a bottom-side colorbar title is taller than the colorbar', function(done) { + Plotly.newPlot(gd, [{ + type: 'scatter', + mode: 'markers', + x: [1, 2, 3], + y: [1, 2, 3], + marker: { + color: [1, 2, 3], + colorbar: { + title: {text: 'Long title', side: 'bottom', font: {size: 60}}, + len: 0.3, + thickness: 30 + } + } + }], {width: 300, height: 120}) + .then(done, done.fail); + }); + + it('does not throw when a right-side horizontal colorbar title is wider than the colorbar', function(done) { + Plotly.newPlot(gd, [{ + type: 'scatter', + mode: 'markers', + x: [1, 2, 3], + y: [1, 2, 3], + marker: { + color: [1, 2, 3], + colorbar: { + orientation: 'h', + title: {text: 'Long title', side: 'right', font: {size: 60}}, + len: 0.3, + thickness: 30 + } + } + }], {width: 300, height: 120}) + .then(done, done.fail); + }); + function assertCB(msg, present, opts) { var expandedMarginR = opts.expandedMarginR; var expandedMarginT = opts.expandedMarginT;