Skip to content

Commit 1aa6d77

Browse files
authored
fix(gauge): y origin can be equal to radius (#486)
* fix(gauge): y origin can be equal to radius * using arc length as approximation for extra padding * pretty changes * fix tests
1 parent 5aa9a4f commit 1aa6d77

File tree

2 files changed

+53
-16
lines changed

2 files changed

+53
-16
lines changed

projects/observability/src/shared/components/gauge/gauge.component.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,17 @@ describe('Gauge component', () => {
4646
spectator.component.onLayoutChange();
4747
expect(spectator.component.rendererData).toEqual({
4848
backgroundArc:
49-
'M-139.64240043768942,-2.3092638912203256e-14A10,10,0,0,1,-149.61685761181008,-10.714285714285738A150,150,0,0,1,149.61685761181008,-10.714285714285714A10,10,0,0,1,139.64240043768942,0L139.64240043768942,0A10,10,0,0,1,129.66794326356876,-9.285714285714285A130,130,0,0,0,-129.66794326356873,-9.2857142857143A10,10,0,0,1,-139.64240043768942,-2.3092638912203256e-14Z',
49+
'M-137.45365478341216,36.83059579592157A7.5,7.5,0,0,1,-146.73136591755903,31.143317998687955A150,150,0,1,1,146.73136591755903,31.143317998687948A7.5,7.5,0,0,1,137.45365478341216,36.83059579592157L137.45365478341216,36.83059579592157A7.5,7.5,0,0,1,132.05822932580313,28.02898619881916A135,135,0,1,0,-132.05822932580313,28.02898619881914A7.5,7.5,0,0,1,-137.45365478341216,36.83059579592157Z',
5050
origin: {
5151
x: 150,
52-
y: 170
52+
y: 150
5353
},
5454
radius: 150,
5555
data: {
5656
value: 80,
5757
maxValue: 100,
5858
valueArc:
59-
'M-139.64240043768942,-2.3092638912203256e-14A10,10,0,0,1,-149.61685761181008,-10.714285714285738A150,150,0,0,1,114.74488132122605,-96.61062162401063A10,10,0,0,1,112.97307508940239,-82.07974357199379L112.97307508940239,-82.07974357199379A10,10,0,0,1,99.44556381172924,-83.72920540747589A130,130,0,0,0,-129.66794326356873,-9.2857142857143A10,10,0,0,1,-139.64240043768942,-2.3092638912203256e-14Z',
59+
'M-137.45365478341216,36.83059579592157A7.5,7.5,0,0,1,-146.73136591755903,31.143317998687955A150,150,0,0,1,88.13185990085536,-121.37864421065183A7.5,7.5,0,0,1,89.55386161673987,-110.58980906724544L89.55386161673987,-110.58980906724544A7.5,7.5,0,0,1,79.31867391076982,-109.24077978958663A135,135,0,0,0,-132.05822932580313,28.02898619881914A7.5,7.5,0,0,1,-137.45365478341216,36.83059579592157Z',
6060
threshold: {
6161
color: '#9e4c41',
6262
end: 90,

projects/observability/src/shared/components/gauge/gauge.component.ts

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ import { Arc, arc, DefaultArcObject } from 'd3-shape';
2424
[attr.d]="rendererData.data.valueArc"
2525
[attr.fill]="rendererData.data.threshold.color"
2626
/>
27-
<text x="0" y="0" class="value-display" [attr.fill]="rendererData.data.threshold.color">
27+
<text x="0" y="-4" class="value-display" [attr.fill]="rendererData.data.threshold.color">
2828
{{ rendererData.data.value }}
2929
</text>
30-
<text x="0" y="24" class="label-display">{{ rendererData.data.threshold.label }}</text>
30+
<text x="0" y="20" class="label-display">{{ rendererData.data.threshold.label }}</text>
3131
</g>
3232
</g>
3333
</svg>
@@ -37,10 +37,10 @@ import { Arc, arc, DefaultArcObject } from 'd3-shape';
3737
changeDetection: ChangeDetectionStrategy.OnPush
3838
})
3939
export class GaugeComponent implements OnChanges {
40-
private static readonly GAUGE_RING_WIDTH: number = 20;
40+
private static readonly GAUGE_RING_WIDTH: number = 15;
4141
private static readonly GAUGE_ARC_CORNER_RADIUS: number = 10;
42-
private static readonly GAUGE_AXIS_PADDING: number = 30;
4342
private static readonly GAUGE_MIN_RADIUS_TO_SHOW_PATH: number = 80;
43+
private static readonly EXTRA_ARC_ANGLE: number = Math.PI / 12;
4444

4545
@Input()
4646
public value?: number;
@@ -76,7 +76,7 @@ export class GaugeComponent implements OnChanges {
7676
const radius = this.buildRadius(boundingBox);
7777

7878
return {
79-
origin: this.buildOrigin(boundingBox),
79+
origin: this.buildOrigin(boundingBox.width, radius),
8080
radius: radius,
8181
backgroundArc: this.buildBackgroundArc(radius),
8282
data: this.buildGaugeData(radius, inputData)
@@ -87,8 +87,8 @@ export class GaugeComponent implements OnChanges {
8787
return this.buildArcGenerator()({
8888
innerRadius: radius - GaugeComponent.GAUGE_RING_WIDTH,
8989
outerRadius: radius,
90-
startAngle: -Math.PI / 2,
91-
endAngle: Math.PI / 2
90+
startAngle: -Math.PI / 2 - GaugeComponent.EXTRA_ARC_ANGLE,
91+
endAngle: Math.PI / 2 + GaugeComponent.EXTRA_ARC_ANGLE
9292
})!;
9393
}
9494

@@ -107,8 +107,8 @@ export class GaugeComponent implements OnChanges {
107107
return this.buildArcGenerator()({
108108
innerRadius: radius - GaugeComponent.GAUGE_RING_WIDTH,
109109
outerRadius: radius,
110-
startAngle: -Math.PI / 2,
111-
endAngle: -Math.PI / 2 + (inputData.value / inputData.maxValue) * Math.PI
110+
startAngle: -Math.PI / 2 - GaugeComponent.EXTRA_ARC_ANGLE,
111+
endAngle: -Math.PI / 2 - GaugeComponent.EXTRA_ARC_ANGLE + (inputData.value / inputData.maxValue) * Math.PI
112112
})!;
113113
}
114114

@@ -117,13 +117,32 @@ export class GaugeComponent implements OnChanges {
117117
}
118118

119119
private buildRadius(boundingBox: ClientRect): number {
120-
return Math.min(boundingBox.height - GaugeComponent.GAUGE_AXIS_PADDING, boundingBox.width / 2);
120+
const width = boundingBox.width;
121+
const height = boundingBox.height;
122+
123+
if (height > width / 2) {
124+
/**
125+
* Since height > width > 2, radius can be treated as (width / 2), but only for semi-circles
126+
*
127+
* If there is an extra angle added to the semicircle,
128+
* radius + extra arc length can over shoots the height
129+
*
130+
* If radius + extra arc length over shoots the height, then radius
131+
* needs to be calculated using the provided height, instead of width / 2
132+
*/
133+
const radius = width / 2;
134+
const extraArcHeight = this.calculateExtraArcLength(radius);
135+
136+
return extraArcHeight + radius <= height ? radius : this.calculateRadius(height);
137+
}
138+
139+
return this.calculateRadius(height);
121140
}
122141

123-
private buildOrigin(boundingBox: ClientRect): Point {
142+
private buildOrigin(width: number, radius: number): Point {
124143
return {
125-
x: boundingBox.width / 2,
126-
y: boundingBox.height - GaugeComponent.GAUGE_AXIS_PADDING
144+
x: width / 2,
145+
y: radius
127146
};
128147
}
129148

@@ -142,6 +161,24 @@ export class GaugeComponent implements OnChanges {
142161
}
143162
}
144163
}
164+
165+
private calculateExtraArcLength(radius: number): number {
166+
return radius * GaugeComponent.EXTRA_ARC_ANGLE;
167+
}
168+
169+
/**
170+
* We want to fit gauge within a specified height
171+
* Approximating arc length, as the extra height required
172+
* to render the EXTRA_ARC_ANGLE in the gauge
173+
*
174+
* height = radius + arc length
175+
* height = radius + radius * EXTRA_ARC_ANGLE
176+
* radius = height / (1 + EXTRA_ARC_ANGLE)
177+
*/
178+
179+
private calculateRadius(height: number): number {
180+
return height / (1 + GaugeComponent.EXTRA_ARC_ANGLE);
181+
}
145182
}
146183

147184
export interface GaugeThreshold {

0 commit comments

Comments
 (0)