Demonstrates how to use Images as Labels using SciChart.js, High Performance JavaScript Charts
drawExample.ts
angular.ts
theme.ts
1import {
2 XyDataSeries,
3 TTextStyle,
4 NumericAxis,
5 FastColumnRenderableSeries,
6 SciChartSurface,
7 TextureManager,
8 EAutoRange,
9 ENumericFormat,
10 createImagesArrayAsync,
11 EFillPaletteMode,
12 EStrokePaletteMode,
13 IFillPaletteProvider,
14 IStrokePaletteProvider,
15 parseColorToUIntArgb,
16 IRenderableSeries,
17 IPointMetadata,
18 PaletteFactory,
19 GradientParams,
20 Point,
21 WaveAnimation,
22 NumberRange,
23 TextAnnotation,
24 EHorizontalAnchorPoint,
25 ECoordinateMode,
26} from "scichart";
27import { appTheme } from "../../../theme";
28
29export const drawExample = (emojiUrls: string[]) => async (rootElement: string | HTMLDivElement) => {
30 // Dataset = 'percentage market share of phones, 2022'
31 const dataset = [
32 { name: "Apple", percent: 28.41 },
33 { name: "Samsung", percent: 28.21 },
34 { name: "Xiaomi", percent: 12.73 },
35 { name: "Huawei", percent: 5.27 },
36 { name: "Oppo", percent: 5.53 },
37 { name: "Vivo", percent: 4.31 },
38 { name: "Realme", percent: 3.16 },
39 { name: "Motorola", percent: 2.33 },
40 { name: "Unknown", percent: 2.19 },
41 { name: "LG", percent: 0.85 },
42 { name: "OnePlus", percent: 1.11 },
43 { name: "Tecno", percent: 1.09 },
44 { name: "Infinix", percent: 0.96 },
45 { name: "Google", percent: 0.77 },
46 { name: "Nokia", percent: 0.45 },
47 ];
48 // Create the SciChartSurface with theme
49 const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
50 theme: appTheme.SciChartJsTheme,
51 });
52
53 const xAxis = new NumericAxis(wasmContext, {
54 // Ensure there can be 1 label per item in the dataset.
55 // Also see major/minor delta in the docs
56 maxAutoTicks: 15,
57 axisTitle: "Mobile phone manufacturer",
58 growBy: new NumberRange(0.02, 0.02),
59 // required for image labels
60 useNativeText: false,
61 });
62 // We need the data value as plain text
63 xAxis.labelProvider.numericFormat = ENumericFormat.NoFormat;
64
65 // SciChart utility function to create HtmlImage elements from urls
66 const emojies = await createImagesArrayAsync(emojiUrls);
67
68 // Override labelProvider.getLabelTexture() to return animage
69 const getLabelTexture = (labelText: string, textureManager: TextureManager, labelStyle: TTextStyle) => {
70 const index = parseInt(labelText);
71 if (!isNaN(index)) {
72 const emoji = emojies[index];
73 if (emoji) {
74 return textureManager.createTextureFromImage(emoji, 40, 40);
75 }
76 }
77 return textureManager.createTextTexture([labelText], labelStyle);
78 };
79 xAxis.labelProvider.getLabelTexture = getLabelTexture;
80
81 // If using asyncLabels = true, override this as well
82 xAxis.labelProvider.getLabelTextureAsync = (
83 labelText: string,
84 textureManager: TextureManager,
85 labelStyle: TTextStyle
86 ) => Promise.resolve(getLabelTexture(labelText, textureManager, labelStyle));
87
88 // Disable shared cache for this provider, otherwise other axes might pick up the emoji textures
89 xAxis.labelProvider.useSharedCache = false;
90
91 sciChartSurface.xAxes.add(xAxis);
92
93 // Create a Y-Axis with standard properties
94 sciChartSurface.yAxes.add(
95 new NumericAxis(wasmContext, {
96 autoRange: EAutoRange.Always,
97 axisTitle: "Market Share (%)",
98 growBy: new NumberRange(0, 0.1),
99 labelPostfix: " %",
100 })
101 );
102
103 // Add a column series.
104 sciChartSurface.renderableSeries.add(
105 new FastColumnRenderableSeries(wasmContext, {
106 // Name index to xvalue for category axis
107 // Map percentage to yvalue
108 // store the manufacturer name in the metadata (used to generate colors)
109 dataSeries: new XyDataSeries(wasmContext, {
110 xValues: dataset.map((row, index) => index),
111 yValues: dataset.map((row) => row.percent),
112 }),
113 strokeThickness: 0,
114 // // Optional datalabels on series. To enable set a style and position
115 // dataLabels: {
116 // horizontalTextPosition: EHorizontalTextPosition.Center,
117 // verticalTextPosition: EVerticalTextPosition.Top,
118 // style: { fontFamily: "Arial", fontSize: 16, padding: new Thickness(0,0,20,0) },
119 // color: appTheme.ForegroundColor,
120 // },
121 // each column occupies 50% of available space
122 dataPointWidth: 0.5,
123 // add a gradient fill in X (why not?)
124 paletteProvider: PaletteFactory.createGradient(
125 wasmContext,
126 new GradientParams(new Point(0, 0), new Point(1, 1), [
127 { offset: 0, color: appTheme.VividPink },
128 { offset: 0.2, color: appTheme.VividOrange },
129 { offset: 0.3, color: appTheme.MutedRed },
130 { offset: 0.5, color: appTheme.VividGreen },
131 { offset: 0.7, color: appTheme.VividSkyBlue },
132 { offset: 0.9, color: appTheme.Indigo },
133 { offset: 1, color: appTheme.DarkIndigo },
134 ]),
135 { enableFill: true, enableStroke: true }
136 ),
137 // Bit more eye candy ;)
138 animation: new WaveAnimation({ duration: 1000 }),
139 })
140 );
141
142 // Add title annotation
143 sciChartSurface.annotations.add(
144 new TextAnnotation({
145 text: "Mobile Phone manufacturer market share (2022)",
146 fontSize: 20,
147 textColor: appTheme.ForegroundColor,
148 x1: 0.5,
149 y1: 0,
150 opacity: 0.77,
151 horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
152 xCoordinateMode: ECoordinateMode.Relative,
153 yCoordinateMode: ECoordinateMode.Relative,
154 })
155 );
156
157 sciChartSurface.zoomExtents();
158 return { sciChartSurface, wasmContext };
159};
160
161export class EmojiPaletteProvider implements IStrokePaletteProvider, IFillPaletteProvider {
162 public readonly strokePaletteMode = EStrokePaletteMode.SOLID;
163 public readonly fillPaletteMode = EFillPaletteMode.SOLID;
164 private readonly pfYellow = parseColorToUIntArgb("FFCC4D");
165 private readonly pfBlue = parseColorToUIntArgb("5DADEC");
166 private readonly pfOrange = parseColorToUIntArgb("F58E01");
167 private readonly pfRed = parseColorToUIntArgb("DE2A43");
168 private readonly pfPink = parseColorToUIntArgb("FE7891");
169
170 // tslint:disable-next-line:no-empty
171 public onAttached(parentSeries: IRenderableSeries): void {}
172
173 // tslint:disable-next-line:no-empty
174 public onDetached(): void {}
175
176 public overrideFillArgb(xValue: number, yValue: number, index: number): number {
177 if (xValue === 0 || xValue === 4 || xValue === 8) {
178 return this.pfYellow;
179 } else if (xValue === 1 || xValue === 7) {
180 return this.pfBlue;
181 } else if (xValue === 2 || xValue === 5) {
182 return this.pfOrange;
183 } else if (xValue === 3 || xValue === 6) {
184 return this.pfRed;
185 } else if (xValue === 9) {
186 return this.pfPink;
187 } else {
188 return undefined;
189 }
190 }
191
192 public overrideStrokeArgb(
193 xValue: number,
194 yValue: number,
195 index: number,
196 opacity?: number,
197 metadata?: IPointMetadata
198 ): number {
199 return undefined;
200 }
201}
202This example demonstrates how to integrate SciChart.js into an Angular application using the scichart-angular component. The chart displays mobile phone market share data and replaces traditional axis labels with images, such as brand logos, to create a more engaging visualization.
The setup uses an Angular standalone component that initializes a SciChartSurface through a custom asynchronous function. This function configures numeric axes and overrides the LabelProvider.getLabelTexture and getLabelTextureAsync methods to load and render images as axis labels. Asynchronous image loading is handled through SciChart.js utilities, ensuring efficient asset management as detailed in the Image Labels documentation. The procedural configuration approach, instead of using a Builder API, allows explicit control over chart properties and performance.
Key features include an animated column series with WaveAnimation and gradient fills, which provide smooth transitions and visual depth. Custom palette providers are used for dynamic color rendering, while asynchronous image loading for axis labels improves both performance and user experience. This design demonstrates how to integrate advanced chart features in a high-performance setting.
The example leverages Angular’s standalone components and dependency injection to encapsulate all chart initialization logic. Developers can refer to the scichart-angular package for integration details and best practices in managing assets as outlined in the Angular Standalone Components guide. The custom label provider implementation, which transforms numeric labels to image textures, follows the techniques presented in the Axis LabelProviders documentation, ensuring a high-quality, extensible solution.

Demonstrates how to use arbitrary text for axis labels, rather than formatted data values, using the new TextLabelProvider

Rotate to create vertical axis labels and fit more on an axis

Demonstrates how to use date-fns and custom logic to format High Precision Date Axes in SciChart.js