Skip to content

Commit b6edba5

Browse files
authored
Merge pull request #4007 from plotly/indicator-fix-delta-pos
indicator: position delta using drawing.bBox
2 parents 44633a1 + a7fae8b commit b6edba5

16 files changed

+207
-117
lines changed

src/snapshot/tosvg.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ module.exports = function toSVG(gd, format, scale) {
8888
// fill whatever container it's displayed in regardless of plot size.
8989
svg.node().style.background = '';
9090

91-
svg.selectAll('text,tspan')
91+
svg.selectAll('text')
9292
.attr({'data-unformatted': null, 'data-math': null})
9393
.each(function() {
9494
var txt = d3.select(this);

src/traces/indicator/constants.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ module.exports = {
1515
bulletPadding: 0.025,
1616
innerRadius: 0.75,
1717
valueThickness: 0.5, // thickness of value bars relative to full thickness,
18-
titlePadding: 5
18+
titlePadding: 5,
19+
horizontalPadding: 10
1920
};

src/traces/indicator/plot.js

+59-49
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ module.exports = function plot(gd, cdModule, transitionOpts, makeOnCompleteCallb
7474
var centerX = size.l + size.w / 2;
7575
var centerY = size.t + size.h / 2;
7676

77-
7877
// Angular gauge size
7978
var radius = Math.min(size.w / 2, size.h); // fill domain
8079
var innerRadius = cn.innerRadius * radius;
@@ -519,59 +518,31 @@ function drawNumbers(gd, plotGroup, cd, opts) {
519518
var trace = cd[0].trace;
520519
var numbersX = opts.numbersX;
521520
var numbersY = opts.numbersY;
522-
var numbersAnchor = anchor[trace.align || 'center'];
521+
var numbersAlign = trace.align || 'center';
522+
var numbersAnchor = anchor[numbersAlign];
523523

524524
var hasTransition = opts.hasTransition;
525525
var transitionOpts = opts.transitionOpts;
526526
var onComplete = opts.onComplete;
527527

528-
var bignumberFontSize, deltaFontSize;
529-
if(trace._hasNumber) bignumberFontSize = trace.number.font.size;
530-
if(trace._hasDelta) deltaFontSize = trace.delta.font.size;
531-
532-
// Position delta relative to bignumber
533-
var deltaDy = 0;
534-
var deltaX = 0;
535-
var bignumberY = 0;
536-
537-
if(trace._hasDelta && trace._hasNumber) {
538-
if(trace.delta.position === 'bottom') {
539-
deltaDy = deltaFontSize * 1.5;
540-
}
541-
if(trace.delta.position === 'top') {
542-
deltaDy = -bignumberFontSize + MID_SHIFT * deltaFontSize;
543-
}
544-
if(trace.delta.position === 'right') {
545-
deltaX = undefined;
546-
}
547-
if(trace.delta.position === 'left') {
548-
deltaX = undefined;
549-
bignumberY = MID_SHIFT * bignumberFontSize / 2;
550-
}
551-
}
552-
deltaDy -= MID_SHIFT * deltaFontSize;
553-
554-
var numbers = Lib.ensureSingle(plotGroup, 'text', 'numbers');
528+
var numbers = Lib.ensureSingle(plotGroup, 'g', 'numbers');
529+
var bignumberbBox, deltabBox;
555530

556531
var data = [];
557532
if(trace._hasNumber) data.push('number');
558533
if(trace._hasDelta) {
559534
data.push('delta');
560535
if(trace.delta.position === 'left') data.reverse();
561536
}
562-
var sel = numbers.selectAll('tspan').data(data);
563-
sel.enter().append('tspan');
537+
var sel = numbers.selectAll('text').data(data);
538+
sel.enter().append('text');
564539
sel
565540
.attr('text-anchor', function() {return numbersAnchor;})
566541
.attr('class', function(d) { return d;})
567-
.attr('dx', function(d, i) {
568-
// Add padding to the second tspan when it's a one-liner
569-
if(i === 1) {
570-
var pos = trace.delta.position;
571-
if(pos === 'left' || pos === 'right') return 10;
572-
}
573-
return null;
574-
});
542+
.attr('x', null)
543+
.attr('y', null)
544+
.attr('dx', null)
545+
.attr('dy', null);
575546
sel.exit().remove();
576547

577548
function drawBignumber() {
@@ -581,11 +552,9 @@ function drawNumbers(gd, plotGroup, cd, opts) {
581552
var bignumberSuffix = trace.number.suffix;
582553
var bignumberPrefix = trace.number.prefix;
583554

584-
var number = numbers.select('tspan.number');
555+
var number = numbers.select('text.number');
585556
number
586-
.call(Drawing.font, trace.number.font)
587-
.attr('x', null)
588-
.attr('dy', bignumberY);
557+
.call(Drawing.font, trace.number.font);
589558

590559
if(hasTransition) {
591560
number
@@ -604,6 +573,11 @@ function drawNumbers(gd, plotGroup, cd, opts) {
604573
} else {
605574
number.text(bignumberPrefix + fmt(cd[0].y) + bignumberSuffix);
606575
}
576+
577+
number.attr('data-unformatted', bignumberPrefix + fmt(cd[0].y) + bignumberSuffix);
578+
bignumberbBox = Drawing.bBox(number.node());
579+
580+
return number;
607581
}
608582

609583
function drawDelta() {
@@ -622,12 +596,10 @@ function drawNumbers(gd, plotGroup, cd, opts) {
622596
var deltaFill = function(d) {
623597
return d.delta >= 0 ? trace.delta.increasing.color : trace.delta.decreasing.color;
624598
};
625-
var delta = numbers.select('tspan.delta');
599+
var delta = numbers.select('text.delta');
626600
delta
627601
.call(Drawing.font, trace.delta.font)
628-
.call(Color.fill, deltaFill(cd[0]))
629-
.attr('x', deltaX)
630-
.attr('dy', deltaDy);
602+
.call(Color.fill, deltaFill(cd[0]));
631603

632604
if(hasTransition) {
633605
delta
@@ -650,11 +622,46 @@ function drawNumbers(gd, plotGroup, cd, opts) {
650622
return deltaFormatText(deltaValue(cd[0]));
651623
});
652624
}
625+
626+
delta.attr('data-unformatted', deltaFormatText(deltaValue(cd[0])));
627+
deltabBox = Drawing.bBox(delta.node());
628+
629+
return delta;
653630
}
654631

655-
if(trace._hasDelta) drawDelta();
632+
// Position delta relative to bignumber
633+
var delta;
634+
if(trace._hasDelta) delta = drawDelta();
656635
if(trace._hasNumber) drawBignumber();
657636

637+
if(trace._hasDelta && trace._hasNumber) {
638+
var bignumberCenter = [
639+
(bignumberbBox.left + bignumberbBox.right) / 2,
640+
(bignumberbBox.top + bignumberbBox.bottom) / 2
641+
];
642+
var deltaCenter = [
643+
(deltabBox.left + deltabBox.right) / 2,
644+
(deltabBox.top + deltabBox.bottom) / 2
645+
];
646+
647+
if(trace.delta.position === 'left') {
648+
delta.attr('dx', bignumberbBox.left - deltabBox.right - cn.horizontalPadding);
649+
delta.attr('dy', bignumberCenter[1] - deltaCenter[1]);
650+
}
651+
if(trace.delta.position === 'right') {
652+
delta.attr('dx', bignumberbBox.right - deltabBox.left + cn.horizontalPadding);
653+
delta.attr('dy', bignumberCenter[1] - deltaCenter[1]);
654+
}
655+
if(trace.delta.position === 'bottom') {
656+
delta.attr('dx', null);
657+
delta.attr('dy', deltabBox.height);
658+
}
659+
if(trace.delta.position === 'top') {
660+
delta.attr('dx', null);
661+
delta.attr('dy', bignumberbBox.top);
662+
}
663+
}
664+
658665
// Resize numbers to fit within space and position
659666
numbers.attr('transform', function() {
660667
var m = opts.numbersScaler(numbers);
@@ -677,7 +684,10 @@ function drawNumbers(gd, plotGroup, cd, opts) {
677684
// Stash the top position of numbersbBox for title positioning
678685
trace._numbersTop = scaleRatio * (numbersbBox.top) + translateY;
679686

680-
return strTranslate(numbersX, translateY) + ' scale(' + scaleRatio + ')';
687+
var ref = numbersbBox[numbersAlign];
688+
if(numbersAlign === 'center') ref = (numbersbBox.left + numbersbBox.right) / 2;
689+
var translateX = numbersX - scaleRatio * ref;
690+
return strTranslate(translateX, translateY) + ' scale(' + scaleRatio + ')';
681691
});
682692
}
683693

34 Bytes
Loading
40 Bytes
Loading
-73 Bytes
Loading
-687 Bytes
Loading
20 Bytes
Loading
39.5 KB
Loading
240 Bytes
Loading
-359 Bytes
Loading
7 Bytes
Loading

test/image/mocks/indicator_datacard.json

-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"type": "indicator",
55
"mode": "number+delta",
66
"number": {
7-
"align": "middle",
87
"suffix": " km/h"
98
},
109
"value": 43,
@@ -17,7 +16,6 @@
1716
"type": "indicator",
1817
"mode": "number+delta",
1918
"number": {
20-
"align": "middle",
2119
"suffix": " km/h"
2220
},
2321
"value": 43,
@@ -30,7 +28,6 @@
3028
"type": "indicator",
3129
"mode": "number+delta",
3230
"number": {
33-
"align": "middle",
3431
"suffix": " km/h"
3532
},
3633
"value": 43,
@@ -43,7 +40,6 @@
4340
"type": "indicator",
4441
"mode": "number+delta",
4542
"number": {
46-
"align": "middle",
4743
"suffix": " km/h"
4844
},
4945
"value": 43,
+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
{
2+
"data": [{
3+
"type": "indicator",
4+
"domain": {"row": 0, "column": 0},
5+
"delta": {"position": "left"},
6+
"align": "left"
7+
}, {
8+
"type": "indicator",
9+
"domain": {"x": [0.05, 0.5], "y": [0.15, 0.35]},
10+
"domain": {"row": 0, "column": 1},
11+
"delta": {"position": "top"},
12+
"align": "left"
13+
}, {
14+
"type": "indicator",
15+
"domain": {"row": 0, "column": 2},
16+
"delta": {"position": "right"},
17+
"align": "left"
18+
}, {
19+
"type": "indicator",
20+
"domain": {"row": 0, "column": 3},
21+
"delta": {"position": "bottom"},
22+
"align": "left"
23+
},
24+
25+
{
26+
"type": "indicator",
27+
"domain": {"row": 1, "column": 0},
28+
"delta": {"position": "left"},
29+
"align": "center"
30+
}, {
31+
"type": "indicator",
32+
"domain": {"x": [0.05, 0.5], "y": [0.15, 0.35]},
33+
"domain": {"row": 1, "column": 1},
34+
"delta": {"position": "top"},
35+
"align": "center"
36+
}, {
37+
"type": "indicator",
38+
"domain": {"row": 1, "column": 2},
39+
"delta": {"position": "right"},
40+
"align": "center"
41+
}, {
42+
"type": "indicator",
43+
"domain": {"row": 1, "column": 3},
44+
"delta": {"position": "bottom"},
45+
"align": "center"
46+
},
47+
48+
{
49+
"type": "indicator",
50+
"domain": {"row": 2, "column": 0},
51+
"delta": {"position": "left"},
52+
"align": "right"
53+
}, {
54+
"type": "indicator",
55+
"domain": {"x": [0.05, 0.5], "y": [0.15, 0.35]},
56+
"domain": {"row": 2, "column": 1},
57+
"delta": {"position": "top"},
58+
"align": "right"
59+
}, {
60+
"type": "indicator",
61+
"domain": {"row": 2, "column": 2},
62+
"delta": {"position": "right"},
63+
"align": "right"
64+
}, {
65+
"type": "indicator",
66+
"domain": {"row": 2, "column": 3},
67+
"delta": {"position": "bottom"},
68+
"align": "right"
69+
}
70+
],
71+
"layout": {
72+
"width": 1000,
73+
"height": 200,
74+
"margin": {"t": 0, "b": 0, "l": 0, "r": 0},
75+
"grid": {"rows": 3, "columns": 4, "pattern": "independent", "xgap": 0, "ygap": 0},
76+
"shapes": [{
77+
"type": "line",
78+
"x0": 0,
79+
"x1": 1,
80+
"y0": 0.33,
81+
"y1": 0.33,
82+
"line": {
83+
"color": "rgba(0, 0, 0, 0.35)",
84+
"width": 1
85+
}
86+
},
87+
{
88+
"type": "line",
89+
"x0": 0,
90+
"x1": 1,
91+
"y0": 0.66,
92+
"y1": 0.66,
93+
"line": {
94+
"color": "rgba(0, 0, 0, 0.35)",
95+
"width": 1
96+
}
97+
},
98+
{
99+
"type": "line",
100+
"x0": 0.25,
101+
"x1": 0.25,
102+
"y0": 0,
103+
"y1": 1,
104+
"line": {
105+
"color": "rgba(0, 0, 0, 0.35)",
106+
"width": 1
107+
}
108+
},
109+
{
110+
"type": "line",
111+
"x0": 0.5,
112+
"x1": 0.5,
113+
"y0": 0,
114+
"y1": 1,
115+
"line": {
116+
"color": "rgba(0, 0, 0, 0.35)",
117+
"width": 1
118+
}
119+
},{
120+
"type": "line",
121+
"x0": 0.75,
122+
"x1": 0.75,
123+
"y0": 0,
124+
"y1": 1,
125+
"line": {
126+
"color": "rgba(0, 0, 0, 0.35)",
127+
"width": 1
128+
}
129+
}],
130+
"template": {
131+
"data": {
132+
"indicator": [{
133+
"mode": "number+delta",
134+
"delta": {"reference": 60},
135+
"value": 120
136+
}]
137+
}
138+
}
139+
}
140+
}

0 commit comments

Comments
 (0)