Demonstrates how to use Images as Labels using SciChart.js, High Performance JavaScript Charts
drawExample.ts
index.tsx
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 // Disable shared cache for this provider, otherwise other axes might pick up the emoji textures
82 xAxis.labelProvider.useSharedCache = false;
83
84 sciChartSurface.xAxes.add(xAxis);
85
86 // Create a Y-Axis with standard properties
87 sciChartSurface.yAxes.add(
88 new NumericAxis(wasmContext, {
89 autoRange: EAutoRange.Always,
90 axisTitle: "Market Share (%)",
91 growBy: new NumberRange(0, 0.1),
92 labelPostfix: " %",
93 })
94 );
95
96 // Add a column series.
97 sciChartSurface.renderableSeries.add(
98 new FastColumnRenderableSeries(wasmContext, {
99 // Name index to xvalue for category axis
100 // Map percentage to yvalue
101 // store the manufacturer name in the metadata (used to generate colors)
102 dataSeries: new XyDataSeries(wasmContext, {
103 xValues: dataset.map((row, index) => index),
104 yValues: dataset.map((row) => row.percent),
105 }),
106 strokeThickness: 0,
107 // // Optional datalabels on series. To enable set a style and position
108 // dataLabels: {
109 // horizontalTextPosition: EHorizontalTextPosition.Center,
110 // verticalTextPosition: EVerticalTextPosition.Top,
111 // style: { fontFamily: "Arial", fontSize: 16, padding: new Thickness(0,0,20,0) },
112 // color: appTheme.ForegroundColor,
113 // },
114 // each column occupies 50% of available space
115 dataPointWidth: 0.5,
116 // add a gradient fill in X (why not?)
117 paletteProvider: PaletteFactory.createGradient(
118 wasmContext,
119 new GradientParams(new Point(0, 0), new Point(1, 1), [
120 { offset: 0, color: appTheme.VividPink },
121 { offset: 0.2, color: appTheme.VividOrange },
122 { offset: 0.3, color: appTheme.MutedRed },
123 { offset: 0.5, color: appTheme.VividGreen },
124 { offset: 0.7, color: appTheme.VividSkyBlue },
125 { offset: 0.9, color: appTheme.Indigo },
126 { offset: 1, color: appTheme.DarkIndigo },
127 ]),
128 { enableFill: true, enableStroke: true }
129 ),
130 // Bit more eye candy ;)
131 animation: new WaveAnimation({ duration: 1000 }),
132 })
133 );
134
135 // Add title annotation
136 sciChartSurface.annotations.add(
137 new TextAnnotation({
138 text: "Mobile Phone manufacturer market share (2022)",
139 fontSize: 20,
140 textColor: appTheme.ForegroundColor,
141 x1: 0.5,
142 y1: 0,
143 opacity: 0.77,
144 horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
145 xCoordinateMode: ECoordinateMode.Relative,
146 yCoordinateMode: ECoordinateMode.Relative,
147 })
148 );
149
150 sciChartSurface.zoomExtents();
151 return { sciChartSurface, wasmContext };
152};
153
154export class EmojiPaletteProvider implements IStrokePaletteProvider, IFillPaletteProvider {
155 public readonly strokePaletteMode = EStrokePaletteMode.SOLID;
156 public readonly fillPaletteMode = EFillPaletteMode.SOLID;
157 private readonly pfYellow = parseColorToUIntArgb("FFCC4D");
158 private readonly pfBlue = parseColorToUIntArgb("5DADEC");
159 private readonly pfOrange = parseColorToUIntArgb("F58E01");
160 private readonly pfRed = parseColorToUIntArgb("DE2A43");
161 private readonly pfPink = parseColorToUIntArgb("FE7891");
162
163 // tslint:disable-next-line:no-empty
164 public onAttached(parentSeries: IRenderableSeries): void {}
165
166 // tslint:disable-next-line:no-empty
167 public onDetached(): void {}
168
169 public overrideFillArgb(xValue: number, yValue: number, index: number): number {
170 if (xValue === 0 || xValue === 4 || xValue === 8) {
171 return this.pfYellow;
172 } else if (xValue === 1 || xValue === 7) {
173 return this.pfBlue;
174 } else if (xValue === 2 || xValue === 5) {
175 return this.pfOrange;
176 } else if (xValue === 3 || xValue === 6) {
177 return this.pfRed;
178 } else if (xValue === 9) {
179 return this.pfPink;
180 } else {
181 return undefined;
182 }
183 }
184
185 public overrideStrokeArgb(
186 xValue: number,
187 yValue: number,
188 index: number,
189 opacity?: number,
190 metadata?: IPointMetadata
191 ): number {
192 return undefined;
193 }
194}
195This example demonstrates how to integrate SciChart.js using JavaScript to create a high-performance column chart with custom image labels replacing traditional text labels on the X-axis. The chart visualizes mobile phone market share data by mapping numeric indices to asynchronously loaded images, creating an engaging and visually appealing representation.
The chart initialization is performed procedurally by creating a SciChartSurface with a images instead of axis labels, as described in the Image Labels Documentation. A numeric X-axis is configured using the NumericAxis and its label provider is customized by overriding the LabelProvider.getLabelTexture and LabelProvider.getLabelTextureAsync methods. This customization leverages the asynchronous helper function createImagesArrayAsync to load images efficiently and use the TextureManager for dynamic texture creation. Furthermore, a gradient fill is applied to the column series using the PaletteFactory, which enhances visual transitions and overall aesthetics.
Key features include the real-time animation of the column series using WaveAnimation and the implementation of custom palette providers for dynamic gradient colors. The asynchronous image loading and deferred texture creation optimize performance, ensuring that the chart runs smoothly even with multiple custom label textures.
This example follows best practices for JavaScript chart integration by using a procedural, step-by-step initialization approach instead of relying on framework-specific hooks or the Builder API. Developers benefit from explicit control over chart customization, as each component—from the axis configuration to the advanced label rendering—is directly managed. For further details on custom label rendering and performance optimization, consult the Image Labels Documentation and review the Performance Tips & Tricks in the SciChart.js documentation.

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