Coloring Series per-point using the PaletteProvider

Demonstrates how create React Charts with per-point coloring using SciChart.js, High Performance JavaScript Charts

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.tsx

RandomWalkGenerator.ts

theme.ts

Copy to clipboard
Minimise
Fullscreen
1import { appTheme } from "../../../theme";
2import { RandomWalkGenerator } from "../../../ExampleData/RandomWalkGenerator";
3
4import {
5    BoxAnnotation,
6    ECoordinateMode,
7    EDataLabelSkipMode,
8    EHorizontalAnchorPoint,
9    ELabelPlacement,
10    EllipsePointMarker,
11    EStrokePaletteMode,
12    FastLineRenderableSeries,
13    HorizontalLineAnnotation,
14    IPointMarkerPaletteProvider,
15    IPointMetadata,
16    IRenderableSeries,
17    IStrokePaletteProvider,
18    NumberRange,
19    NumericAxis,
20    parseColorToUIntArgb,
21    SciChartSurface,
22    TextAnnotation,
23    Thickness,
24    TPointMarkerArgb,
25    XyDataSeries,
26    XyScatterRenderableSeries,
27} from "scichart";
28
29export const drawExample = async (rootElement: string | HTMLDivElement) => {
30    // Create a SciChartSurface
31    const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
32        theme: appTheme.SciChartJsTheme,
33    });
34
35    // Create the X,Y Axis
36    sciChartSurface.xAxes.add(new NumericAxis(wasmContext, { maxAutoTicks: 5 }));
37    sciChartSurface.yAxes.add(new NumericAxis(wasmContext, { maxAutoTicks: 5, growBy: new NumberRange(0.05, 0.2) }));
38
39    const { xValues, yValues } = new RandomWalkGenerator().Seed(1337).getRandomWalkSeries(50);
40
41    let THRESHOLD_HIGH_LEVEL = 0;
42    let THRESHOLD_LOW_LEVEL = -2;
43    // For performance reasons PaletteProviders require colors as Argb numbers e.g. 0xFFFF0000 = red
44    const THRESHOLD_LOW_COLOR_ARGB = parseColorToUIntArgb(appTheme.VividPink);
45    const THRESHOLD_HIGH_COLOR_ARGB = parseColorToUIntArgb(appTheme.VividTeal);
46
47    const getColor = (yValue: number) => {
48        if (yValue < THRESHOLD_LOW_LEVEL) {
49            return THRESHOLD_LOW_COLOR_ARGB;
50        }
51        if (yValue > THRESHOLD_HIGH_LEVEL) {
52            return THRESHOLD_HIGH_COLOR_ARGB;
53        }
54        // Undefined means use default series stroke on this data-point
55        return undefined;
56    };
57
58    // PaletteProvider API allows for per-point colouring, filling of points or areas based on a rule
59    // see PaletteProvider API for more details
60    const strokePaletteProvider: IStrokePaletteProvider = {
61        onAttached(parentSeries: IRenderableSeries): void {},
62        onDetached(): void {},
63        strokePaletteMode: EStrokePaletteMode.GRADIENT,
64        // This function called once per data-point for line stroke. Colors returned must be in ARGB format (uint) e.g. 0xFF0000FF is Red
65        overrideStrokeArgb(
66            xValue: number,
67            yValue: number,
68            index: number,
69            opacity?: number,
70            metadata?: IPointMetadata
71        ): number {
72            return getColor(yValue);
73        },
74    };
75
76    // Create a line series with threshold palette provider
77    sciChartSurface.renderableSeries.add(
78        new FastLineRenderableSeries(wasmContext, {
79            dataSeries: new XyDataSeries(wasmContext, { xValues, yValues }),
80            strokeThickness: 4,
81            stroke: appTheme.VividOrange,
82            dataLabels: {
83                style: { fontFamily: "Arial", fontSize: 13, padding: Thickness.fromNumber(5) },
84                color: appTheme.PaleSkyBlue,
85                skipMode: EDataLabelSkipMode.SkipIfOverlapPrevious,
86            },
87            paletteProvider: strokePaletteProvider,
88        })
89    );
90
91    const pointPaletteProvider: IPointMarkerPaletteProvider = {
92        strokePaletteMode: EStrokePaletteMode.SOLID,
93        onAttached(parentSeries: IRenderableSeries): void {},
94        onDetached(): void {},
95        // This function called once per data-point for scatter fill
96        overridePointMarkerArgb(
97            xValue: number,
98            yValue: number,
99            index: number,
100            opacity?: number,
101            metadata?: IPointMetadata
102        ): TPointMarkerArgb {
103            const color = getColor(yValue);
104            return { stroke: color, fill: color };
105        },
106    };
107
108    // Create a scatter series with threshold paletteprovider
109    sciChartSurface.renderableSeries.add(
110        new XyScatterRenderableSeries(wasmContext, {
111            dataSeries: new XyDataSeries(wasmContext, { xValues, yValues }),
112            pointMarker: new EllipsePointMarker(wasmContext, {
113                width: 7,
114                height: 7,
115                stroke: appTheme.VividOrange,
116                fill: appTheme.VividOrange,
117            }),
118            paletteProvider: pointPaletteProvider,
119        })
120    );
121
122    // Add annotations to fill the threshold areas
123    const boxHighAnnotation = new BoxAnnotation({
124        x1: 0,
125        x2: 1,
126        y1: THRESHOLD_LOW_LEVEL,
127        y2: -9999,
128        fill: appTheme.VividPink + "11",
129        strokeThickness: 0,
130        xCoordinateMode: ECoordinateMode.Relative,
131    });
132    sciChartSurface.annotations.add(boxHighAnnotation);
133    const boxLowAnnotation = new BoxAnnotation({
134        x1: 0,
135        x2: 1,
136        y1: THRESHOLD_HIGH_LEVEL,
137        y2: 9999,
138        fill: appTheme.VividTeal + "11",
139        strokeThickness: 0,
140        xCoordinateMode: ECoordinateMode.Relative,
141    });
142    sciChartSurface.annotations.add(boxLowAnnotation);
143    // Add annotations to show the thresholds
144    const thresholdHighAnnotation = new HorizontalLineAnnotation({
145        stroke: appTheme.VividTeal,
146        strokeThickness: 2,
147        strokeDashArray: [3, 3],
148        y1: THRESHOLD_HIGH_LEVEL,
149        labelPlacement: ELabelPlacement.TopRight,
150        labelValue: "High warning",
151        axisLabelFill: appTheme.VividTeal,
152        axisFontSize: 16,
153        showLabel: true,
154        isEditable: true,
155        onDrag: (args) => {
156            // When the vertical line is dragged, update the
157            // threshold palette and redraw the SciChartSurface
158            THRESHOLD_HIGH_LEVEL = thresholdHighAnnotation.y1;
159            boxLowAnnotation.y1 = thresholdHighAnnotation.y1;
160            sciChartSurface.invalidateElement();
161        },
162    });
163    sciChartSurface.annotations.add(thresholdHighAnnotation);
164    const thresholdLowAnnotation = new HorizontalLineAnnotation({
165        stroke: appTheme.VividPink,
166        strokeThickness: 2,
167        strokeDashArray: [3, 3],
168        labelPlacement: ELabelPlacement.BottomLeft,
169        y1: THRESHOLD_LOW_LEVEL,
170        labelValue: "Low warning",
171        axisLabelFill: appTheme.VividPink,
172        axisFontSize: 16,
173        showLabel: true,
174        isEditable: true,
175        onDrag: (args) => {
176            // When the vertical line is dragged, update the
177            // threshold palette and redraw the SciChartSurface
178            THRESHOLD_LOW_LEVEL = thresholdLowAnnotation.y1;
179            boxHighAnnotation.y1 = THRESHOLD_LOW_LEVEL;
180            sciChartSurface.invalidateElement();
181        },
182    });
183    sciChartSurface.annotations.add(thresholdLowAnnotation);
184    // Add title annotation
185    sciChartSurface.annotations.add(
186        new TextAnnotation({
187            text: "Per point colouring in SciChart.js. Can be applied to lines, areas, scatter points and bubbles",
188            fontSize: 16,
189            textColor: appTheme.ForegroundColor,
190            x1: 0,
191            y1: 0,
192            xCoordShift: 10,
193            yCoordShift: 10,
194            opacity: 0.77,
195            horizontalAnchorPoint: EHorizontalAnchorPoint.Left,
196            xCoordinateMode: ECoordinateMode.Relative,
197            yCoordinateMode: ECoordinateMode.Relative,
198        })
199    );
200
201    return { sciChartSurface, wasmContext };
202};
203

Per Point Coloring - React

Overview

This example demonstrates how to create a high performance chart in React using SciChart.js with per-point coloring. In this implementation, both line and scatter series are rendered with data points whose colors are dynamically updated based on predefined threshold values. The example highlights how to integrate SciChart.js into React applications using the <SciChartReact/> component, following best practices for React integration.

Technical Implementation

The chart is initialized by passing an asynchronous chart drawing function to the <SciChartReact/> component. This function creates the SciChartSurface, configures numeric axes, and generates a random walk data series. Custom IStrokePaletteProvider and IPointMarkerPaletteProvider implementations are used to determine the color for each data point based on its y-value. The line series uses a stroke palette provider while the scatter series uses a point marker palette provider. Both these providers return color values in ARGB format as required by SciChart.js. For additional technical details on the PaletteProvider API, review the PaletteProvider documentation.

Features and Capabilities

This example highlights several advanced features:

  • Per-Point Coloring: Dynamic recoloring of series elements (both line and scatter) based on custom logic.
  • Interactive Annotations: Draggable horizontal line annotations update threshold levels in real-time, which in turn update the chart’s color palette.
  • Integrated Data Labeling: Data labels are conditionally displayed and styled, ensuring clarity even when points are densely packed. These capabilities provide a comprehensive demonstration of how to leverage SciChart.js for interactive and visually rich charting experiences in React.

Integration and Best Practices

The implementation shows how to seamlessly integrate SciChart.js within a React framework by using the <SciChartReact/> component to encapsulate chart initialization logic. This ensures that chart configuration and rendering follow React’s declarative model while benefiting from SciChart.js’s performance optimizations and WebGL rendering capabilities. Developers are encouraged to refer to the React Charts with SciChart.js tutorial for project setup and more advanced integration techniques. Additionally, performance optimization techniques such as reducing re-rendering and efficient resource management are highlighted, aligning with the advice provided in the Performance Optimisation of JavaScript Applications & Charts article.

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