Chart Axis Image labels

Demonstrates how to use Images as Labels using SciChart.js, High Performance JavaScript Charts

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.tsx

theme.ts

Copy to clipboard
Minimise
Fullscreen
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}
195

Image Labels on Axis Example (React)

Overview

This example demonstrates how to use images as axis labels within a SciChart.js chart embedded in a React application. Instead of traditional text labels, images representing mobile phone manufacturers are used to provide a more engaging visualization of market share data.

Technical Implementation

The integration leverages the SciChartReact component to initialize a high performance chart in React. A custom asynchronous function initializes the SciChartSurface, sets up Numeric axes, and adds a column series with gradient fills and animations. The example uses the asynchronous helper function createImagesArrayAsync to load images dynamically, a process that is key to efficient resource management as described in Image Labels. Customization is achieved by overriding the axis label provider’s LabelProvider.getLabelTexture and getLabelTextureAsync methods, allowing image textures to be generated for each label based on corresponding index values.

Features and Capabilities

The chart features a real-time animated column series enhanced by a gradient fill, implemented using a gradient palette provider created by PaletteFactory and a WaveAnimation. Text annotations and dynamic scaling using sciChartSurface.zoomExtents() further enhance the visualization by providing contextual information. The method of directly configuring the chart through a React component ensures a clear separation of concerns and maintains optimal performance.

Integration and Best Practices

This example follows best practices for React integration by encapsulating the SciChartSurface creation inside a functional component, ensuring seamless lifecycle management and asynchronous operation handling. Developers interested in advanced customization can refer to the Tutorial on setting up a project with scichart-react and learn more about custom label providers to override default behaviors for enhanced chart aesthetics. The example purposefully avoids using the builder API, opting instead for direct procedural configuration to provide clear control over the chart’s customization and performance optimizations.

SciChart Ltd, 16 Beaufort Court, Admirals Way, Docklands, London, E14 9XL.