Skip to content

Commit 2913c6e

Browse files
committed
text position DRAFT
1 parent ec44d87 commit 2913c6e

File tree

1 file changed

+84
-24
lines changed

1 file changed

+84
-24
lines changed

src/traces/bar/plot.js

Lines changed: 84 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts, makeOnCompleteCallback)
396396
Drawing.singlePointStyle(di, sel, trace, styleFns, gd);
397397
}
398398

399-
appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, lxFunc, lyFunc, opts, makeOnCompleteCallback);
399+
appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, lxFunc, lyFunc, r, opts, makeOnCompleteCallback);
400400

401401
if(plotinfo.layerClipId) {
402402
Drawing.hideOutsideRangePoint(di, bar.select('text'), xa, ya, trace.xcalendar, trace.ycalendar);
@@ -413,7 +413,7 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts, makeOnCompleteCallback)
413413
Registry.getComponentMethod('errorbars', 'plot')(gd, bartraces, plotinfo, opts);
414414
}
415415

416-
function appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, lxFunc, lyFunc, opts, makeOnCompleteCallback) {
416+
function appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, lxFunc, lyFunc, r, opts, makeOnCompleteCallback) {
417417
var xa = plotinfo.xaxis;
418418
var ya = plotinfo.yaxis;
419419

@@ -450,6 +450,7 @@ function appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, lxFunc, lyFunc,
450450

451451
var calcBar = cd[i];
452452
var isOutmostBar = !inStackOrRelativeMode || calcBar._outmost;
453+
var hasB = calcBar.hasB;
453454

454455
if(!text ||
455456
textPosition === 'none' ||
@@ -532,6 +533,8 @@ function appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, lxFunc, lyFunc,
532533
(barWidth >= textWidth * (barHeight / textHeight)) :
533534
(barHeight >= textHeight * (barWidth / textWidth));
534535

536+
// TODO: Rounding needs to be considered when deciding
537+
// whether text fits inside bar
535538
if(textHasSize && (
536539
fitsInside ||
537540
fitsInsideIfRotated ||
@@ -592,6 +595,8 @@ function appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, lxFunc, lyFunc,
592595
anchor: insidetextanchor,
593596
lxFunc: lxFunc,
594597
lyFunc: lyFunc,
598+
hasB: hasB,
599+
r: r,
595600
});
596601
}
597602

@@ -628,22 +633,14 @@ function toMoveInsideBar(x0, x1, y0, y1, textBB, opts) {
628633
var leftToRight = opts.leftToRight || 0; // left: -1, center: 0, right: 1
629634
var toRight = (leftToRight + 1) / 2;
630635
var toLeft = 1 - toRight;
631-
var lxFunc = opts.lxFunc;
632-
var lyFunc = opts.lyFunc;
636+
var hasB = opts.hasB;
637+
var r = opts.r;
633638

634639
var textWidth = textBB.width;
635640
var textHeight = textBB.height;
636641

637-
var lx, ly, refPos;
638-
if(isHorizontal) {
639-
refPos = (anchor === 'middle') ? Math.abs(x1 - x0) / 2 : TEXTPAD;
640-
lx = Math.abs(x1 - x0);
641-
ly = lyFunc ? lyFunc(refPos) : Math.abs(y1 - y0);
642-
} else {
643-
refPos = (anchor === 'middle') ? Math.abs(y1 - y0) / 2 : TEXTPAD;
644-
lx = lxFunc ? lxFunc(refPos) : Math.abs(x1 - x0);
645-
ly = Math.abs(y1 - y0);
646-
}
642+
var lx = Math.abs(x1 - x0);
643+
var ly = Math.abs(y1 - y0);
647644

648645
// compute remaining space
649646
var textpad = (
@@ -658,21 +655,31 @@ function toMoveInsideBar(x0, x1, y0, y1, textBB, opts) {
658655
if((angle === 'auto') &&
659656
!(textWidth <= lx && textHeight <= ly) &&
660657
(textWidth > lx || textHeight > ly) && (
661-
!(textWidth > ly || textHeight > lx) ||
662-
((textWidth < textHeight) !== (lx < ly))
663-
)) {
658+
!(textWidth > ly || textHeight > lx) ||
659+
((textWidth < textHeight) !== (lx < ly))
660+
)) {
664661
rotate += 90;
665662
}
666663

667664
var t = getRotatedTextSize(textBB, rotate);
668665

669-
var scale = 1;
670-
if(constrained) {
671-
scale = Math.min(
672-
1,
673-
lx / t.x,
674-
ly / t.y
675-
);
666+
var scale, padForRounding;
667+
// Scale text for rounded bars
668+
if(r && r > TEXTPAD) {
669+
var scaleAndPad = scaleTextForRoundedBar(x0, x1, y0, y1, t, r, isHorizontal, hasB);
670+
scale = scaleAndPad.scale;
671+
padForRounding = scaleAndPad.pad;
672+
// Scale text for non-rounded bars
673+
} else {
674+
scale = 1;
675+
if(constrained) {
676+
scale = Math.min(
677+
1,
678+
lx / t.x,
679+
ly / t.y
680+
);
681+
}
682+
padForRounding = 0;
676683
}
677684

678685
// compute text and target positions
@@ -690,6 +697,11 @@ function toMoveInsideBar(x0, x1, y0, y1, textBB, opts) {
690697
var anchorY = 0;
691698
if(isStart || isEnd) {
692699
var extrapad = (isHorizontal ? t.x : t.y) / 2;
700+
701+
if(r && (hasB || isEnd)) {
702+
extrapad += padForRounding;
703+
}
704+
693705
var dir = isHorizontal ? dirSign(x0, x1) : dirSign(y0, y1);
694706

695707
if(isHorizontal) {
@@ -723,6 +735,54 @@ function toMoveInsideBar(x0, x1, y0, y1, textBB, opts) {
723735
};
724736
}
725737

738+
function scaleTextForRoundedBar(x0, x1, y0, y1, t, r, isHorizontal, hasB) {
739+
var barWidth = Math.max(0, Math.abs(x1 - x0) - 2 * TEXTPAD);
740+
var barHeight = Math.max(0, Math.abs(y1 - y0) - 2 * TEXTPAD);
741+
var R = r - TEXTPAD;
742+
var rX = hasB ? R * 2 : (isHorizontal ? R : 2 * R);
743+
var rY = hasB ? R * 2 : (isHorizontal ? 2 * R : R);
744+
var a, b, c;
745+
var scale, pad;
746+
747+
// Calculate how much extra padding is needed for bar
748+
// TODO: This is the equation I worked out, but it seems to give a value that's too small
749+
if(isHorizontal) {
750+
pad = Math.max(0, R - Math.sqrt(R * R + (t.y - barHeight) / 2 - R));
751+
} else {
752+
pad = Math.max(0, R - Math.sqrt(R * R + (t.x - barWidth) / 2 - R));
753+
}
754+
755+
if(t.y / t.x >= barHeight / (barWidth - rX)) {
756+
// Case 1 (Tall text)
757+
scale = barHeight / t.y;
758+
pad = 0;
759+
} else if(t.y / t.x <= (barHeight - rY) / barWidth) {
760+
// Case 2 (Wide text)
761+
scale = barWidth / t.x;
762+
pad = 0;
763+
} else if(!hasB && isHorizontal) {
764+
// Case 3a (Quadratic case, two side corners are rounded)
765+
a = t.x * t.x + t.y * t.y / 4;
766+
b = t.y * (2 * R - barHeight) + 2 * t.x * (R - barWidth);
767+
c = (R - barHeight / 2) * (R - barHeight / 2) + (R - barWidth) * (R - barWidth) - R * R;
768+
scale = (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a);
769+
} else if(!hasB) {
770+
// Case 3b (Quadratic case, two top/bottom corners are rounded)
771+
a = t.x * t.x / 4 + t.y * t.y;
772+
b = 2 * t.x * (R - barHeight) + t.y * (2 * R - barWidth);
773+
c = (R - barHeight) * (R - barHeight) + (R - barWidth / 2) * (R - barWidth / 2) - R * R;
774+
scale = (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a);
775+
} else {
776+
// Case 4 (Quadratic case, all four corners are rounded)
777+
// TODO: This gives a scale factor that's way too large, text overflows boundaries
778+
a = (t.x * t.x + t.y * t.y) / 4;
779+
b = t.y * (2 * R - barHeight) + t.x * (2 * R - barWidth);
780+
c = (R - barHeight / 2) * (R - barHeight / 2) + (R - barWidth / 2) * (R - barWidth / 2) - R * R;
781+
scale = (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a);
782+
}
783+
return { scale: scale, pad: pad };
784+
}
785+
726786
function toMoveOutsideBar(x0, x1, y0, y1, textBB, opts) {
727787
var isHorizontal = !!opts.isHorizontal;
728788
var constrained = !!opts.constrained;

0 commit comments

Comments
 (0)