From acb01aebbd5247a46a16b9151614f9f9a8ce464c Mon Sep 17 00:00:00 2001 From: archmoj Date: Fri, 29 Nov 2019 14:13:14 -0500 Subject: [PATCH] move bar transform functions from bar/plot to bar/helpers --- src/traces/bar/helpers.js | 152 +++++++++++++++++++++++++++++ src/traces/bar/index.js | 2 +- src/traces/bar/plot.js | 176 ++-------------------------------- src/traces/funnel/plot.js | 2 +- src/traces/funnelarea/plot.js | 3 +- src/traces/histogram/index.js | 2 +- src/traces/treemap/plot.js | 2 +- src/traces/waterfall/plot.js | 2 +- 8 files changed, 167 insertions(+), 174 deletions(-) diff --git a/src/traces/bar/helpers.js b/src/traces/bar/helpers.js index aa368a0f939..488fcbb8710 100644 --- a/src/traces/bar/helpers.js +++ b/src/traces/bar/helpers.js @@ -11,6 +11,7 @@ var isNumeric = require('fast-isnumeric'); var tinycolor = require('tinycolor2'); var isArrayOrTypedArray = require('../../lib').isArrayOrTypedArray; +var TEXTPAD = require('./constants').TEXTPAD; exports.coerceString = function(attributeDefinition, value, defaultValue) { if(typeof value === 'string') { @@ -74,3 +75,154 @@ exports.getLineWidth = function(trace, di) { return w; }; + +exports.dirSign = function(a, b) { + return (a < b) ? 1 : -1; +}; + +exports.toMoveInsideBar = function(x0, x1, y0, y1, textBB, opts) { + var isHorizontal = !!opts.isHorizontal; + var constrained = !!opts.constrained; + var angle = opts.angle || 0; + var anchor = opts.anchor || 0; + + var textWidth = textBB.width; + var textHeight = textBB.height; + var lx = Math.abs(x1 - x0); + var ly = Math.abs(y1 - y0); + + var textpad = ( + lx > (2 * TEXTPAD) && + ly > (2 * TEXTPAD) + ) ? TEXTPAD : 0; + + lx -= 2 * textpad; + ly -= 2 * textpad; + + var autoRotate = (angle === 'auto'); + var isAutoRotated = false; + if(autoRotate && + !(textWidth <= lx && textHeight <= ly) && + (textWidth > lx || textHeight > ly) && ( + !(textWidth > ly || textHeight > lx) || + ((textWidth < textHeight) !== (lx < ly)) + )) { + isAutoRotated = true; + } + + if(isAutoRotated) { + // don't rotate yet only swap bar width with height + var tmp = ly; + ly = lx; + lx = tmp; + } + + var rotate = getRotateFromAngle(angle); + var absSin = Math.abs(Math.sin(Math.PI / 180 * rotate)); + var absCos = Math.abs(Math.cos(Math.PI / 180 * rotate)); + + // compute and apply text padding + var dx = Math.max(lx * absCos, ly * absSin); + var dy = Math.max(lx * absSin, ly * absCos); + + var scale = (constrained) ? + Math.min(dx / textWidth, dy / textHeight) : + Math.max(absCos, absSin); + + scale = Math.min(1, scale); + + // compute text and target positions + var targetX = (x0 + x1) / 2; + var targetY = (y0 + y1) / 2; + + if(anchor !== 'middle') { // case of 'start' or 'end' + var targetWidth = scale * (isHorizontal !== isAutoRotated ? textHeight : textWidth); + var targetHeight = scale * (isHorizontal !== isAutoRotated ? textWidth : textHeight); + textpad += 0.5 * (targetWidth * absSin + targetHeight * absCos); + + if(isHorizontal) { + textpad *= exports.dirSign(x0, x1); + targetX = (anchor === 'start') ? x0 + textpad : x1 - textpad; + } else { + textpad *= exports.dirSign(y0, y1); + targetY = (anchor === 'start') ? y0 + textpad : y1 - textpad; + } + } + + var textX = (textBB.left + textBB.right) / 2; + var textY = (textBB.top + textBB.bottom) / 2; + + // lastly apply auto rotation + if(isAutoRotated) rotate += 90; + + return { + textX: textX, + textY: textY, + targetX: targetX, + targetY: targetY, + scale: scale, + rotate: rotate + }; +}; + +exports.toMoveOutsideBar = function(x0, x1, y0, y1, textBB, opts) { + var isHorizontal = !!opts.isHorizontal; + var constrained = !!opts.constrained; + var angle = opts.angle || 0; + + var textWidth = textBB.width; + var textHeight = textBB.height; + var lx = Math.abs(x1 - x0); + var ly = Math.abs(y1 - y0); + + var textpad; + // Keep the padding so the text doesn't sit right against + // the bars, but don't factor it into barWidth + if(isHorizontal) { + textpad = (ly > 2 * TEXTPAD) ? TEXTPAD : 0; + } else { + textpad = (lx > 2 * TEXTPAD) ? TEXTPAD : 0; + } + + // compute rotate and scale + var scale = 1; + if(constrained) { + scale = (isHorizontal) ? + Math.min(1, ly / textHeight) : + Math.min(1, lx / textWidth); + } + + var rotate = getRotateFromAngle(angle); + var absSin = Math.abs(Math.sin(Math.PI / 180 * rotate)); + var absCos = Math.abs(Math.cos(Math.PI / 180 * rotate)); + + // compute text and target positions + var targetWidth = scale * (isHorizontal ? textHeight : textWidth); + var targetHeight = scale * (isHorizontal ? textWidth : textHeight); + textpad += 0.5 * (targetWidth * absSin + targetHeight * absCos); + + var targetX = (x0 + x1) / 2; + var targetY = (y0 + y1) / 2; + + if(isHorizontal) { + targetX = x1 - textpad * exports.dirSign(x1, x0); + } else { + targetY = y1 + textpad * exports.dirSign(y0, y1); + } + + var textX = (textBB.left + textBB.right) / 2; + var textY = (textBB.top + textBB.bottom) / 2; + + return { + textX: textX, + textY: textY, + targetX: targetX, + targetY: targetY, + scale: scale, + rotate: rotate + }; +}; + +function getRotateFromAngle(angle) { + return (angle === 'auto') ? 0 : angle; +} diff --git a/src/traces/bar/index.js b/src/traces/bar/index.js index 7bddd744c53..37949c50109 100644 --- a/src/traces/bar/index.js +++ b/src/traces/bar/index.js @@ -18,7 +18,7 @@ module.exports = { crossTraceCalc: require('./cross_trace_calc').crossTraceCalc, colorbar: require('../scatter/marker_colorbar'), arraysToCalcdata: require('./arrays_to_calcdata'), - plot: require('./plot').plot, + plot: require('./plot'), style: require('./style').style, styleOnSelect: require('./style').styleOnSelect, hoverPoints: require('./hover').hoverPoints, diff --git a/src/traces/bar/plot.js b/src/traces/bar/plot.js index d67a5abb677..f210dbf05fd 100644 --- a/src/traces/bar/plot.js +++ b/src/traces/bar/plot.js @@ -21,7 +21,6 @@ var tickText = require('../../plots/cartesian/axes').tickText; var style = require('./style'); var helpers = require('./helpers'); -var constants = require('./constants'); var attributes = require('./attributes'); var attributeText = attributes.text; @@ -29,7 +28,7 @@ var attributeTextPosition = attributes.textposition; var appendArrayPointValue = require('../../components/fx/helpers').appendArrayPointValue; -var TEXTPAD = constants.TEXTPAD; +var TEXTPAD = require('./constants').TEXTPAD; function keyFunc(d) {return d.id;} function getKeyFunc(trace) { @@ -38,10 +37,6 @@ function getKeyFunc(trace) { } } -function dirSign(a, b) { - return (a < b) ? 1 : -1; -} - function getXY(di, xa, ya, isHorizontal) { var s = []; var p = []; @@ -79,7 +74,7 @@ function hasTransition(transitionOpts) { return transitionOpts && transitionOpts.duration > 0; } -function plot(gd, plotinfo, cdModule, traceLayer, opts, makeOnCompleteCallback) { +module.exports = function plot(gd, plotinfo, cdModule, traceLayer, opts, makeOnCompleteCallback) { var xa = plotinfo.xaxis; var ya = plotinfo.yaxis; var fullLayout = gd._fullLayout; @@ -152,11 +147,11 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts, makeOnCompleteCallback) // in waterfall mode `between` we need to adjust bar end points to match the connector width if(adjustPixel && !isBlank) { if(isHorizontal) { - x0 -= dirSign(x0, x1) * adjustPixel; - x1 += dirSign(x0, x1) * adjustPixel; + x0 -= helpers.dirSign(x0, x1) * adjustPixel; + x1 += helpers.dirSign(x0, x1) * adjustPixel; } else { - y0 -= dirSign(y0, y1) * adjustPixel; - y1 += dirSign(y0, y1) * adjustPixel; + y0 -= helpers.dirSign(y0, y1) * adjustPixel; + y1 += helpers.dirSign(y0, y1) * adjustPixel; } } @@ -235,7 +230,7 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts, makeOnCompleteCallback) // error bars are on the top Registry.getComponentMethod('errorbars', 'plot')(gd, bartraces, plotinfo, opts); -} +}; function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts, makeOnCompleteCallback) { var xa = plotinfo.xaxis; @@ -381,7 +376,7 @@ function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts, ma trace.constraintext === 'both' || trace.constraintext === 'outside'; - transform = Lib.getTextTransform(toMoveOutsideBar(x0, x1, y0, y1, textBB, { + transform = Lib.getTextTransform(helpers.toMoveOutsideBar(x0, x1, y0, y1, textBB, { isHorizontal: isHorizontal, constrained: constrained, angle: trace.textangle @@ -391,7 +386,7 @@ function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts, ma trace.constraintext === 'both' || trace.constraintext === 'inside'; - transform = Lib.getTextTransform(toMoveInsideBar(x0, x1, y0, y1, textBB, { + transform = Lib.getTextTransform(helpers.toMoveInsideBar(x0, x1, y0, y1, textBB, { isHorizontal: isHorizontal, constrained: constrained, angle: trace.textangle, @@ -402,153 +397,6 @@ function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts, ma transition(textSelection, opts, makeOnCompleteCallback).attr('transform', transform); } -function getRotateFromAngle(angle) { - return (angle === 'auto') ? 0 : angle; -} - -function toMoveInsideBar(x0, x1, y0, y1, textBB, opts) { - var isHorizontal = !!opts.isHorizontal; - var constrained = !!opts.constrained; - var angle = opts.angle || 0; - var anchor = opts.anchor || 0; - - var textWidth = textBB.width; - var textHeight = textBB.height; - var lx = Math.abs(x1 - x0); - var ly = Math.abs(y1 - y0); - - var textpad = ( - lx > (2 * TEXTPAD) && - ly > (2 * TEXTPAD) - ) ? TEXTPAD : 0; - - lx -= 2 * textpad; - ly -= 2 * textpad; - - var autoRotate = (angle === 'auto'); - var isAutoRotated = false; - if(autoRotate && - !(textWidth <= lx && textHeight <= ly) && - (textWidth > lx || textHeight > ly) && ( - !(textWidth > ly || textHeight > lx) || - ((textWidth < textHeight) !== (lx < ly)) - )) { - isAutoRotated = true; - } - - if(isAutoRotated) { - // don't rotate yet only swap bar width with height - var tmp = ly; - ly = lx; - lx = tmp; - } - - var rotate = getRotateFromAngle(angle); - var absSin = Math.abs(Math.sin(Math.PI / 180 * rotate)); - var absCos = Math.abs(Math.cos(Math.PI / 180 * rotate)); - - // compute and apply text padding - var dx = Math.max(lx * absCos, ly * absSin); - var dy = Math.max(lx * absSin, ly * absCos); - - var scale = (constrained) ? - Math.min(dx / textWidth, dy / textHeight) : - Math.max(absCos, absSin); - - scale = Math.min(1, scale); - - // compute text and target positions - var targetX = (x0 + x1) / 2; - var targetY = (y0 + y1) / 2; - - if(anchor !== 'middle') { // case of 'start' or 'end' - var targetWidth = scale * (isHorizontal !== isAutoRotated ? textHeight : textWidth); - var targetHeight = scale * (isHorizontal !== isAutoRotated ? textWidth : textHeight); - textpad += 0.5 * (targetWidth * absSin + targetHeight * absCos); - - if(isHorizontal) { - textpad *= dirSign(x0, x1); - targetX = (anchor === 'start') ? x0 + textpad : x1 - textpad; - } else { - textpad *= dirSign(y0, y1); - targetY = (anchor === 'start') ? y0 + textpad : y1 - textpad; - } - } - - var textX = (textBB.left + textBB.right) / 2; - var textY = (textBB.top + textBB.bottom) / 2; - - // lastly apply auto rotation - if(isAutoRotated) rotate += 90; - - return { - textX: textX, - textY: textY, - targetX: targetX, - targetY: targetY, - scale: scale, - rotate: rotate - }; -} - -function toMoveOutsideBar(x0, x1, y0, y1, textBB, opts) { - var isHorizontal = !!opts.isHorizontal; - var constrained = !!opts.constrained; - var angle = opts.angle || 0; - - var textWidth = textBB.width; - var textHeight = textBB.height; - var lx = Math.abs(x1 - x0); - var ly = Math.abs(y1 - y0); - - var textpad; - // Keep the padding so the text doesn't sit right against - // the bars, but don't factor it into barWidth - if(isHorizontal) { - textpad = (ly > 2 * TEXTPAD) ? TEXTPAD : 0; - } else { - textpad = (lx > 2 * TEXTPAD) ? TEXTPAD : 0; - } - - // compute rotate and scale - var scale = 1; - if(constrained) { - scale = (isHorizontal) ? - Math.min(1, ly / textHeight) : - Math.min(1, lx / textWidth); - } - - var rotate = getRotateFromAngle(angle); - var absSin = Math.abs(Math.sin(Math.PI / 180 * rotate)); - var absCos = Math.abs(Math.cos(Math.PI / 180 * rotate)); - - // compute text and target positions - var targetWidth = scale * (isHorizontal ? textHeight : textWidth); - var targetHeight = scale * (isHorizontal ? textWidth : textHeight); - textpad += 0.5 * (targetWidth * absSin + targetHeight * absCos); - - var targetX = (x0 + x1) / 2; - var targetY = (y0 + y1) / 2; - - if(isHorizontal) { - targetX = x1 - textpad * dirSign(x1, x0); - } else { - targetY = y1 + textpad * dirSign(y0, y1); - } - - var textX = (textBB.left + textBB.right) / 2; - var textY = (textBB.top + textBB.bottom) / 2; - - return { - textX: textX, - textY: textY, - targetX: targetX, - targetY: targetY, - scale: scale, - rotate: rotate - }; -} - function getText(fullLayout, calcTrace, index, xa, ya) { var trace = calcTrace[0].trace; var texttemplate = trace.texttemplate; @@ -713,9 +561,3 @@ function calcTextinfo(calcTrace, index, xa, ya) { return text.join('
'); } - -module.exports = { - plot: plot, - toMoveInsideBar: toMoveInsideBar, - toMoveOutsideBar: toMoveOutsideBar -}; diff --git a/src/traces/funnel/plot.js b/src/traces/funnel/plot.js index 39290306f82..70523e5b676 100644 --- a/src/traces/funnel/plot.js +++ b/src/traces/funnel/plot.js @@ -11,7 +11,7 @@ var d3 = require('d3'); var Lib = require('../../lib'); var Drawing = require('../../components/drawing'); -var barPlot = require('../bar/plot').plot; +var barPlot = require('../bar/plot'); module.exports = function plot(gd, plotinfo, cdModule, traceLayer) { var fullLayout = gd._fullLayout; diff --git a/src/traces/funnelarea/plot.js b/src/traces/funnelarea/plot.js index 29ce263c1d1..2f8a212082f 100644 --- a/src/traces/funnelarea/plot.js +++ b/src/traces/funnelarea/plot.js @@ -14,8 +14,7 @@ var Drawing = require('../../components/drawing'); var Lib = require('../../lib'); var svgTextUtils = require('../../lib/svg_text_utils'); -var barPlot = require('../bar/plot'); -var toMoveInsideBar = barPlot.toMoveInsideBar; +var toMoveInsideBar = require('../bar/helpers').toMoveInsideBar; var pieHelpers = require('../pie/helpers'); var piePlot = require('../pie/plot'); diff --git a/src/traces/histogram/index.js b/src/traces/histogram/index.js index b8b22a50fc1..b7a99e7589b 100644 --- a/src/traces/histogram/index.js +++ b/src/traces/histogram/index.js @@ -29,7 +29,7 @@ module.exports = { supplyLayoutDefaults: require('../bar/layout_defaults'), calc: require('./calc').calc, crossTraceCalc: require('../bar/cross_trace_calc').crossTraceCalc, - plot: require('../bar/plot').plot, + plot: require('../bar/plot'), layerName: 'barlayer', style: require('../bar/style').style, styleOnSelect: require('../bar/style').styleOnSelect, diff --git a/src/traces/treemap/plot.js b/src/traces/treemap/plot.js index f6fadac0891..ad68193b214 100644 --- a/src/traces/treemap/plot.js +++ b/src/traces/treemap/plot.js @@ -15,7 +15,7 @@ var helpers = require('../sunburst/helpers'); var Lib = require('../../lib'); var TEXTPAD = require('../bar/constants').TEXTPAD; -var toMoveInsideBar = require('../bar/plot').toMoveInsideBar; +var toMoveInsideBar = require('../bar/helpers').toMoveInsideBar; var constants = require('./constants'); var drawDescendants = require('./draw_descendants'); diff --git a/src/traces/waterfall/plot.js b/src/traces/waterfall/plot.js index 61a7ab6580c..c29e6afbf80 100644 --- a/src/traces/waterfall/plot.js +++ b/src/traces/waterfall/plot.js @@ -11,7 +11,7 @@ var d3 = require('d3'); var Lib = require('../../lib'); var Drawing = require('../../components/drawing'); -var barPlot = require('../bar/plot').plot; +var barPlot = require('../bar/plot'); module.exports = function plot(gd, plotinfo, cdModule, traceLayer) { var fullLayout = gd._fullLayout;