Demonstrates interaction by dragging vertical and horizontal line thresholds on a mountain chart. As the thresholds move, the chart colour updates. The vertical mountain fill is done using a separate renderableSeries and a dataFilter which reshapes the data to draw only the portion above the threshold.
drawExample.ts
index.tsx
ExampleDataProvider.ts
theme.ts
1import {
2 BaseDataSeries,
3 ECoordinateMode,
4 EFillPaletteMode,
5 EHorizontalAnchorPoint,
6 ELabelPlacement,
7 EStrokePaletteMode,
8 EVerticalAnchorPoint,
9 FastMountainRenderableSeries,
10 GradientParams,
11 HorizontalLineAnnotation,
12 IFillPaletteProvider,
13 IRenderableSeries,
14 IStrokePaletteProvider,
15 MouseWheelZoomModifier,
16 NumberRange,
17 NumericAxis,
18 parseColorToUIntArgb,
19 Point,
20 SciChartSurface,
21 TextAnnotation,
22 VerticalLineAnnotation,
23 XyDataSeries,
24 XyFilterBase,
25 XyyFilterBase,
26 ZoomExtentsModifier,
27 ZoomPanModifier,
28} from "scichart";
29import { ExampleDataProvider } from "../../../ExampleData/ExampleDataProvider";
30import { appTheme } from "../../../theme";
31
32// tslint:disable:no-empty
33// tslint:disable:max-line-length
34
35class ThresholdFilter extends XyFilterBase {
36 private thresholdProperty = 1;
37
38 constructor(originalSeries: BaseDataSeries, threshold: number, dataSeriesName: string) {
39 super(originalSeries, { dataSeriesName });
40 this.thresholdProperty = threshold;
41 this.filterAll();
42 }
43
44 public get threshold() {
45 return this.thresholdProperty;
46 }
47
48 public set threshold(value: number) {
49 this.thresholdProperty = value;
50 this.filterAll();
51 }
52
53 protected filterAll() {
54 this.clear();
55 this.filter(0, this.getOriginalCount());
56 }
57
58 protected filterOnAppend(count: number): void {
59 // Overriding this so we do not have to reprocess the entire series on append
60 this.filter(this.getOriginalCount() - count, count);
61 }
62
63 protected filter(start: number, count: number): void {
64 const xValues: number[] = [];
65 const yValues: number[] = [];
66 for (let i = start; i < start + count; i++) {
67 xValues.push(this.getOriginalXValues().get(i));
68 const y = this.getOriginalYValues().get(i);
69 if (this.threshold > 0 && y < this.threshold) {
70 yValues.push(NaN);
71 } else if (y < 0) {
72 yValues.push(Math.max(y, this.threshold));
73 } else {
74 yValues.push(y);
75 }
76 }
77 this.appendRange(xValues, yValues);
78 }
79
80 protected onClear() {
81 this.clear();
82 }
83}
84
85export const drawExample = async (rootElement: string | HTMLDivElement) => {
86 const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
87 theme: appTheme.SciChartJsTheme,
88 });
89
90 // Add an XAxis, YAxis
91 sciChartSurface.xAxes.add(new NumericAxis(wasmContext));
92 sciChartSurface.yAxes.add(new NumericAxis(wasmContext, { growBy: new NumberRange(0.1, 0.1) }));
93
94 // Create a paletteprovider to colour the series depending on a threshold value
95 const thresholdPalette = new XThresholdPaletteProvider(8, appTheme.VividTeal);
96
97 // Add a Column series with some values to the chart
98 const { xValues, yValues } = ExampleDataProvider.getDampedSinewave(0, 10, 0, 0.001, 3000, 10);
99 const dataSeries = new XyDataSeries(wasmContext, {
100 xValues,
101 yValues,
102 });
103 sciChartSurface.renderableSeries.add(
104 new FastMountainRenderableSeries(wasmContext, {
105 stroke: appTheme.PaleSkyBlue,
106 strokeThickness: 5,
107 zeroLineY: 0.0,
108 dataSeries,
109 fillLinearGradient: new GradientParams(new Point(0, 0), new Point(0, 1), [
110 { color: appTheme.VividSkyBlue, offset: 0 },
111 { color: appTheme.VividSkyBlue + "77", offset: 1 },
112 ]),
113 paletteProvider: thresholdPalette,
114 })
115 );
116
117 const thresholdFilter = new ThresholdFilter(dataSeries, 4.0, "TopFill");
118 const topFill = new FastMountainRenderableSeries(wasmContext, {
119 stroke: appTheme.PaleSkyBlue,
120 strokeThickness: 5,
121 zeroLineY: 4.0,
122 dataSeries: thresholdFilter,
123 fill: appTheme.MutedOrange,
124 paletteProvider: thresholdPalette,
125 });
126 sciChartSurface.renderableSeries.add(topFill);
127
128 // Add a label to tell user what to do
129 const textAnnotation = new TextAnnotation({
130 verticalAnchorPoint: EVerticalAnchorPoint.Bottom,
131 xCoordinateMode: ECoordinateMode.Relative,
132 x1: 0.5,
133 y1: 4.2,
134 fontSize: 22,
135 text: "Drag the lines!",
136 textColor: "White",
137 });
138 // Add a horizontal threshold at Y=5
139 const horizontalLine = new HorizontalLineAnnotation({
140 y1: 4.0,
141 isEditable: true,
142 showLabel: true,
143 stroke: appTheme.VividOrange,
144 strokeThickness: 3,
145 axisLabelFill: appTheme.VividOrange,
146 axisLabelStroke: appTheme.ForegroundColor,
147 labelPlacement: ELabelPlacement.Axis,
148 onDrag: (args) => {
149 // When the horizontal line is dragged, update the
150 // threshold palette and redraw the SciChartSurface
151 topFill.zeroLineY = Math.max(0, horizontalLine.y1);
152 thresholdFilter.threshold = horizontalLine.y1;
153 textAnnotation.y1 = horizontalLine.y1 + 0.2;
154 sciChartSurface.invalidateElement();
155 },
156 });
157 sciChartSurface.annotations.add(horizontalLine);
158 sciChartSurface.annotations.add(textAnnotation);
159
160 // Add a vertical line
161 const verticalLine = new VerticalLineAnnotation({
162 x1: 8,
163 strokeThickness: 3,
164 isEditable: true,
165 showLabel: true,
166 stroke: appTheme.VividTeal,
167 axisLabelFill: appTheme.VividTeal,
168 axisLabelStroke: appTheme.ForegroundColor,
169 labelPlacement: ELabelPlacement.Axis,
170 onDrag: (args) => {
171 // When the vertical line is dragged, update the
172 // threshold palette and redraw the SciChartSurface
173 thresholdPalette.xThresholdValue = verticalLine.x1;
174 sciChartSurface.invalidateElement();
175 },
176 });
177 sciChartSurface.annotations.add(verticalLine);
178
179 // Add instructions
180 sciChartSurface.annotations.add(
181 new TextAnnotation({
182 x1: 0,
183 y1: 0,
184 xAxisId: "history",
185 xCoordinateMode: ECoordinateMode.Relative,
186 yCoordinateMode: ECoordinateMode.Relative,
187 horizontalAnchorPoint: EHorizontalAnchorPoint.Left,
188 verticalAnchorPoint: EVerticalAnchorPoint.Top,
189 text: "SciChart.js supports editable, draggable annotations and dynamic color/fill rules. Drag a threshold line!",
190 textColor: appTheme.ForegroundColor + "77",
191 })
192 );
193
194 // Optional: Add some interactivity modifiers
195 sciChartSurface.chartModifiers.add(new ZoomPanModifier({ enableZoom: true }));
196 sciChartSurface.chartModifiers.add(new ZoomExtentsModifier());
197 sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier());
198
199 return { sciChartSurface, wasmContext };
200};
201
202/**
203 * A paletteprovider which colours a series if X value over a threshold, else use default colour
204 */
205export class XThresholdPaletteProvider implements IFillPaletteProvider {
206 public readonly fillPaletteMode: EFillPaletteMode = EFillPaletteMode.GRADIENT;
207 public readonly strokePaletteMode: EStrokePaletteMode = EStrokePaletteMode.GRADIENT;
208 public xThresholdValue: number;
209 private readonly xColor: number;
210
211 constructor(xThresholdValue: number, xColor: string) {
212 this.xThresholdValue = xThresholdValue;
213 this.xColor = parseColorToUIntArgb(xColor);
214 }
215
216 onAttached(parentSeries: IRenderableSeries): void {}
217
218 onDetached(): void {}
219
220 overrideFillArgb(xValue: number, yValue: number, index: number, opacity?: number): number {
221 // When the x-value of the series is greater than the x threshold
222 // fill with the xColor
223 if (xValue > this.xThresholdValue) {
224 return this.xColor;
225 }
226 // Undefined means use default color
227 return undefined;
228 }
229}
230This example demonstrates how to integrate SciChart.js with a React application to create an interactive mountain chart with draggable horizontal and vertical thresholds. The chart updates in real time as users drag the annotations and dynamically modifies the underlying data through a custom data filter, showcasing a powerful blend of interactivity and performance.
The React integration is achieved using the <SciChartReact/> component with an initChart callback that draws the chart using SciChartSurface. Interactive annotations are implemented with onDrag event handlers to update both the chart visuals and the custom data filtering logic provided by the ThresholdFilter class. This filter, which extends SciChart's XyFilterBase, ensures that only data above a dynamically adjustable threshold is displayed. For more detail on integrating React with SciChart.js, refer to the Creating a SciChart React Component from the Ground Up guide. Additionally, the custom filtering logic follows the practices described in Creating a Custom Filter.
The example offers real-time chart updates through interactive draggable annotations that adjust horizontal and vertical thresholds. A custom palette provider (XThresholdPaletteProvider) dynamically modifies the fill color of chart regions based on the defined thresholds, using techniques explained in The PaletteProvider API. High-performance rendering is ensured through the use of FastMountainRenderableSeries, which optimizes the rendering of large datasets.
This implementation exemplifies best practices for integrating SciChart.js within a React environment by leveraging core React concepts along with the powerful <SciChartReact/> component. The use of interactive modifiers like ZoomPanModifier, ZoomExtentsModifier, and MouseWheelZoomModifier further enhances the user experience by enabling efficient zooming and panning. Developers can explore advanced React integration and performance optimization techniques in the SciChart ecosystem by consulting the React Charts with SciChart.js: Introducing “SciChart React” article and the Tutorial 03 - Adding Zooming, Panning Behavior documentation.
This example serves as a comprehensive reference for developers looking to create scalable, interactive charting applications in React using SciChart.js.

Demonstrates how to place Annotations (lines, arrows, markers, text) over a React Chart using SciChart.js Annotations API

Demonstrates per-point coloring in JavaScript chart types with SciChart.js PaletteProvider API

Demonstrates how to place Buy/Sell arrow markers on a React Stock Chart using SciChart.js - Annotations API

Demonstrates how to edit Annotations (shapes, boxes, lines, text, horizontal and vertical line) over a React Chart using SciChart.js Annotations API

Demonstrates how to color areas of the chart surface using background Annotations using SciChart.js Annotations API

Demonstrates how layering works a React Chart using SciChart.js Annotations API

Build Responsive React HTML Annotations with SciChart. Use the advanced CSS container queries for responsive text layout and custom design. View demo now.

React HTML Chart Control example demonstrates advanced HTML annotation integration and how to render HTML components within charts. Try the SciChart demo.