Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api-goldens/charts-ng/gauge/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export class SiChartGaugeComponent extends SiChartBaseComponent implements OnCha
readonly unit: _angular_core.InputSignal<string>;
readonly unitsOnSplit: _angular_core.InputSignal<boolean>;
readonly value: _angular_core.InputSignal<number>;
readonly valueArcStart: _angular_core.InputSignal<number | undefined>;
readonly valueFormatter: _angular_core.InputSignal<((val: number) => string) | undefined>;
}

Expand Down
1 change: 1 addition & 0 deletions api-goldens/charts-ng/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ export class SiChartGaugeComponent extends SiChartBaseComponent implements OnCha
readonly unit: i0.InputSignal<string>;
readonly unitsOnSplit: i0.InputSignal<boolean>;
readonly value: i0.InputSignal<number>;
readonly valueArcStart: i0.InputSignal<number | undefined>;
readonly valueFormatter: i0.InputSignal<((val: number) => string) | undefined>;
}

Expand Down
32 changes: 32 additions & 0 deletions projects/charts-ng/gauge/si-chart-gauge.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { SiChartGaugeComponent } from './si-chart-gauge.component';
[minValue]="minValue"
[maxValue]="maxValue"
[value]="value"
[valueArcStart]="valueArcStart"
[title]="title"
[subTitle]="subTitle"
/>`
Expand All @@ -23,6 +24,7 @@ class TestHostComponent {
minValue!: number;
maxValue!: number;
value!: number;
valueArcStart?: number;
title?: string;
subTitle?: string;
}
Expand Down Expand Up @@ -77,4 +79,34 @@ describe('SiChartGaugeComponent', () => {
component.chartGaugeComponent().setValue(5);
expect(getOption(component.chartGaugeComponent()).series[2].data[0].value).toEqual(5);
});

it('should start the value arc at a custom value without changing the gauge range', () => {
const fixture = TestBed.createComponent(TestHostComponent);
const component = fixture.componentInstance;
component.minValue = 0;
component.maxValue = 200;
component.valueArcStart = 45;
component.value = 90;
fixture.detectChanges();

const options = getOption(component.chartGaugeComponent());
expect(options.series[0]).toMatchObject({ min: 0, max: 200, startAngle: 180 });
expect(options.series[2]).toMatchObject({
min: 45,
max: 200,
startAngle: 139.5,
endAngle: 0,
data: [{ value: 90 }]
});
});

it('should start the value arc at the minimum value by default', () => {
const { component } = createChartWithTestData();
expect(getOption(component.chartGaugeComponent()).series[2]).toMatchObject({
min: 0,
max: 50,
startAngle: 180,
data: [{ value: 2 }]
});
});
});
62 changes: 57 additions & 5 deletions projects/charts-ng/gauge/si-chart-gauge.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ export class SiChartGaugeComponent extends SiChartBaseComponent implements OnCha
* @defaultValue 0
*/
readonly value = input(0);
/** The value at which the main value arc starts.
* Values outside the gauge range are clamped to `minValue` or `maxValue`.
* When not set, the value arc starts at `minValue`.
*/
readonly valueArcStart = input<number>();
/** The number of intervals displayed on the gauge axis. */
readonly splitSteps = input<number>();
/** Whether the number of gauge-axis intervals adapts to the component size.
Expand Down Expand Up @@ -160,7 +165,10 @@ export class SiChartGaugeComponent extends SiChartBaseComponent implements OnCha
}
(this.actualOptions.series![0] as any).axisLine.show = hasIndicator;

this.setAxisLineColor(newColors, (this.actualOptions.series![2] as any).axisLine);
this.setAxisLineColor(
this.getValueArcColors(newColors),
(this.actualOptions.series![2] as any).axisLine
);
this.refreshSeries();
}

Expand All @@ -169,6 +177,44 @@ export class SiChartGaugeComponent extends SiChartBaseComponent implements OnCha
axisLine.lineStyle.color = colors;
}

private getValueArcColors(colors: [number, string][]): [number, string][] {
const minValue = this.minValue();
const maxValue = this.maxValue();
const valueArcStart = this.valueArcStart();
if (
valueArcStart === undefined ||
valueArcStart <= minValue ||
valueArcStart >= maxValue ||
maxValue <= minValue
) {
return colors;
}

const startRatio = (valueArcStart - minValue) / (maxValue - minValue);
return colors
.filter(([threshold]) => threshold > startRatio)
.map(([threshold, color]) => [(threshold - startRatio) / (1 - startRatio), color]);
}

private getValueArcOptions(): { min: number; startAngle: number; showProgress: boolean } {
const minValue = this.minValue();
const maxValue = this.maxValue();
const valueArcStart = this.valueArcStart();
if (valueArcStart === undefined || valueArcStart <= minValue || maxValue <= minValue) {
return { min: minValue, startAngle: 180, showProgress: true };
}
if (valueArcStart >= maxValue) {
return { min: minValue, startAngle: 180, showProgress: false };
}

const startRatio = (valueArcStart - minValue) / (maxValue - minValue);
return {
min: valueArcStart,
startAngle: 180 * (1 - startRatio),
showProgress: true
};
}

private getResponsiveConfig(): {
outerRadius: number;
center: (string | number)[];
Expand Down Expand Up @@ -240,6 +286,7 @@ export class SiChartGaugeComponent extends SiChartBaseComponent implements OnCha
protected override applyOptions(): void {
const resp = this.getResponsiveConfig();
const hasIndicator = !!this.segments().length;
const valueArcOptions = this.getValueArcOptions();

const splitNumber =
this.responsiveSplitSteps() && resp.splits ? resp.splits : this.splitSteps();
Expand Down Expand Up @@ -310,13 +357,13 @@ export class SiChartGaugeComponent extends SiChartBaseComponent implements OnCha
type: 'gauge',
silent: false,
radius: resp.outerRadius,
startAngle: 180,
startAngle: valueArcOptions.startAngle,
endAngle: 0,
min: this.minValue(),
min: valueArcOptions.min,
max: this.maxValue(),
splitNumber,
progress: {
show: true,
show: valueArcOptions.showProgress,
itemStyle: { color: 'auto' },
width: resp.progressWidth
},
Expand Down Expand Up @@ -391,15 +438,20 @@ export class SiChartGaugeComponent extends SiChartBaseComponent implements OnCha
if (this.chart && (changes.palette || changes.colors || changes.segments)) {
this.updateColors();
}
const updateValueArcColors =
this.chart && (changes.minValue || changes.maxValue || changes.valueArcStart);
changes.forceAll = new SimpleChange(false, true, false);
super.ngOnChanges(changes);
if (updateValueArcColors) {
this.updateColors();
}
}

protected override applyDataZoom(): void {}

protected override afterChartResize(): void {
this.applyOptions();
this.refreshSeries();
this.updateColors();
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/app/examples/si-charts/gauge/chart.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
[unit]="chartData.unit"
[minValue]="chartData.minValue"
[maxValue]="chartData.maxValue"
[value]="chartData.value"
[valueArcStart]="chartData.valueArcStart"
[splitSteps]="chartData.splitSteps"
[colors]="chartData.colors"
[segments]="chartData.segments"
Expand Down
5 changes: 4 additions & 1 deletion src/app/examples/si-charts/gauge/gauge-basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export class SampleComponent implements OnDestroy {
unit: ' km/h',
minValue: 0,
maxValue: 180,
value: 90,
valueArcStart: 45,
splitSteps: 12,
colors: ['#28bf66', '#f3cb55', '#d92b48', '#9544ed'],
segments: [0.2, 0.5, 0.7, 1],
Expand All @@ -43,7 +45,8 @@ export class SampleComponent implements OnDestroy {
startLive(): void {
this.chartData.liveUpdate = true;
this.liveSubscription = interval(1000).subscribe(() => {
this.chart().setValue(Math.random() * this.chart().maxValue());
this.chartData.value = Math.random() * this.chart().maxValue();
this.chart().setValue(this.chartData.value);
});
}
}
Loading