Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | 28x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 1x 13x 13x 14x 4x 4x 4x 14x 1x 1x 1x 1x 1x 5x 1x 1x 1x 1x 18x 18x 18x 18x 18x 18x 18x 18x 90x | /**
* Copyright (c) Siemens 2016 - 2026
* SPDX-License-Identifier: MIT
*/
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
import { Coordinate, makePolyline } from '@siemens/native-charts-ng/utils';
export interface MicrochartLineSeries {
/** Series values */
values: number[];
/**
* Use a data-color. See: {@link https://element.siemens.io/fundamentals/colors/data-visualization-colors/#tokens}
*
* @example "element-data-10"
*/
colorToken: string;
}
@Component({
selector: 'si-microchart-line',
templateUrl: './si-microchart-line.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SiMicrochartLineComponent {
/**
* Microchart line series.
* Example series can be:
* @example
* ```ts
* Series: MicrochartLineSeries = { values: [2, 3, 6, 5, 4, 7, 8], colorToken: 'element-data-10' };
* ```
*/
readonly series = input.required<MicrochartLineSeries>();
/** @defaultValue 64 */
readonly width = input<number>(64);
/** @defaultValue 24 */
readonly height = input<number>(24);
/**
* Display circular markers at each data point on the line.
* When enabled, markers help highlight individual values and improve readability.
*
* @defaultValue false
*/
readonly showMarkers = input<boolean>(false);
/**
* Sets whether the area under the chart line should be filled.
*
* @defaultValue false
*/
readonly showArea = input<boolean>(false);
/**
* Line width in pixels.
*
* @defaultValue 2
*/
readonly lineWidth = input<number>(2);
/**
* Marker color token. If not provided, uses the series color token.
* Use a data-color. See: {@link https://element.siemens.io/fundamentals/colors/data-visualization-colors/#tokens}
*
* @example "element-data-2"
*/
readonly markerColor = input<string>();
protected readonly markerRadius = computed(() => this.lineWidth());
protected readonly viewBox = computed(() => {
return `0 0 ${this.width()} ${this.height()}`;
});
protected readonly path = computed(() => {
const series = this.series();
if (!series || series.values.length < 2) {
return '';
}
const points = this.mapToCoordinates(series.values);
return makePolyline(points);
});
protected readonly markerPoints = computed(() => {
const series = this.series();
Iif (series?.values.length === 0) {
return [];
}
return this.mapToCoordinates(series.values);
});
protected readonly areaPath = computed(() => {
const series = this.series();
Iif (!series || series.values.length < 2) {
return '';
}
const points = this.mapToCoordinates(series.values);
let path = `M ${points[0].x} ${this.height()}`;
points.forEach(point => {
path += `L ${point.x} ${point.y}`;
});
path += `L ${points[points.length - 1].x} ${this.height()} Z`;
return path;
});
private static instanceCounter = 0;
protected readonly gradientId = `gradient-line-${SiMicrochartLineComponent.instanceCounter++}`;
private mapToCoordinates(values: number[]): Coordinate[] {
const max = Math.max(...values);
const min = Math.min(...values);
// Calculate available space, accounting for marker radius or line width
// This helps avoid the markers on the edges or the edges of the line getting cropped.
const horizontalMargin = this.showMarkers() ? this.markerRadius() : this.lineWidth() / 2;
const verticalMargin = this.showMarkers() ? this.markerRadius() : this.lineWidth() / 2;
const availableWidth = this.width() - horizontalMargin * 2;
const availableHeight = this.height() - verticalMargin * 2;
const scaleX = values.length > 1 ? availableWidth / (values.length - 1) : 0;
const scaleY = max !== min ? availableHeight / (max - min) : 1;
return values.map((value, i) => ({
x: horizontalMargin + i * scaleX,
y: this.height() - verticalMargin - (value - min) * scaleY
}));
}
}
|