Realtime Percentage Change using Filter

Demonstrates how to use a ScaleOffsetFilter to convert data to a Percentage Change with realtime updates, 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";
3import {
4    SciChartSurface,
5    NumericAxis,
6    NumberRange,
7    EAutoRange,
8    XyDataSeries,
9    XyScaleOffsetFilter,
10    FastLineRenderableSeries,
11    HitTestInfo,
12    XySeriesInfo,
13    SeriesInfo,
14    ZoomPanModifier,
15    ZoomExtentsModifier,
16    RolloverModifier,
17    TextAnnotation,
18    EHorizontalAnchorPoint,
19    EVerticalAnchorPoint,
20    ECoordinateMode,
21    EAnnotationLayer,
22    ENumericFormat,
23} from "scichart";
24
25// Custom formatNumber function to avoid conflicts
26const customFormatNumber = (value: number, format: ENumericFormat, precision: number) => {
27    return value.toFixed(precision);
28};
29
30const getScaleValue = (dataSeries: XyDataSeries, zeroXValue: number) => {
31    const dataLength = dataSeries.count();
32    let zeroIndex = -1;
33    for (let i = 0; i < dataLength; i++) {
34        const xValue = dataSeries.getNativeXValues().get(i);
35        if (xValue >= zeroXValue) {
36            zeroIndex = i;
37            break;
38        }
39    }
40    if (zeroIndex === -1) {
41        return 1;
42    }
43    return 100 / dataSeries.getNativeYValues().get(zeroIndex);
44};
45
46class TransformedSeries extends FastLineRenderableSeries {
47    public originalSeries: XyDataSeries;
48
49    public override getSeriesInfo(hitTestInfo: HitTestInfo): SeriesInfo {
50        const info = new XySeriesInfo(this, hitTestInfo);
51        if (this.originalSeries && info.dataSeriesIndex !== undefined) {
52            info.yValue = this.originalSeries.getNativeYValues().get(info.dataSeriesIndex);
53        }
54        return info;
55    }
56}
57
58export const drawExample = async (rootElement: string | HTMLDivElement, usePercentage: boolean) => {
59    const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
60        theme: appTheme.SciChartJsTheme,
61    });
62
63    const xAxis = new NumericAxis(wasmContext);
64    sciChartSurface.xAxes.add(xAxis);
65
66    const yAxis = new NumericAxis(wasmContext, {
67        autoRange: EAutoRange.Always,
68        labelPostfix: usePercentage ? "%" : "",
69        labelPrecision: usePercentage ? 0 : 1,
70        growBy: new NumberRange(0.1, 0.1),
71    });
72
73    yAxis.labelProvider.formatCursorLabel = (value: number) => customFormatNumber(value, ENumericFormat.Decimal, 1);
74    sciChartSurface.yAxes.add(yAxis);
75
76    const lineSeries = new TransformedSeries(wasmContext, {
77        strokeThickness: 3,
78        stroke: appTheme.VividSkyBlue,
79    });
80    sciChartSurface.renderableSeries.add(lineSeries);
81
82    const data0 = new RandomWalkGenerator().Seed(1337).getRandomWalkSeries(100);
83    const dataSeries1 = new XyDataSeries(wasmContext, { xValues: data0.xValues, yValues: data0.yValues });
84
85    const transform1 = new XyScaleOffsetFilter(dataSeries1, { offset: -100 });
86
87    xAxis.visibleRangeChanged.subscribe(
88        (args) => (transform1.scale = getScaleValue(dataSeries1, args.visibleRange.min))
89    );
90
91    if (usePercentage) {
92        lineSeries.dataSeries = transform1;
93        lineSeries.originalSeries = dataSeries1;
94    } else {
95        lineSeries.dataSeries = dataSeries1;
96    }
97
98    const lineSeries2 = new TransformedSeries(wasmContext, {
99        strokeThickness: 3,
100        stroke: appTheme.VividOrange,
101    });
102    sciChartSurface.renderableSeries.add(lineSeries2);
103
104    const data1 = new RandomWalkGenerator().Seed(0).getRandomWalkSeries(100);
105    const dataSeries2 = new XyDataSeries(wasmContext, { xValues: data1.xValues, yValues: data1.yValues });
106
107    const transform2 = new XyScaleOffsetFilter(dataSeries2, { offset: -100 });
108    xAxis.visibleRangeChanged.subscribe(
109        (args) => (transform2.scale = getScaleValue(dataSeries2, args.visibleRange.min))
110    );
111
112    if (usePercentage) {
113        lineSeries2.dataSeries = transform2;
114        lineSeries2.originalSeries = dataSeries2;
115    } else {
116        lineSeries2.dataSeries = dataSeries2;
117    }
118
119    sciChartSurface.chartModifiers.add(new ZoomPanModifier({ enableZoom: true }));
120    sciChartSurface.chartModifiers.add(new ZoomExtentsModifier());
121    sciChartSurface.chartModifiers.add(new RolloverModifier({ rolloverLineStroke: appTheme.VividTeal }));
122
123    sciChartSurface.annotations.add(
124        new TextAnnotation({
125            text: "Toggle between original data & Percentage Changed on chart",
126            fontSize: 16,
127            textColor: appTheme.ForegroundColor,
128            x1: 0.5,
129            y1: 0,
130            opacity: 0.77,
131            horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
132            xCoordinateMode: ECoordinateMode.Relative,
133            yCoordinateMode: ECoordinateMode.Relative,
134        })
135    );
136
137    const watermarkText = usePercentage ? "Percentage Changed" : "Original Data";
138    sciChartSurface.annotations.add(
139        new TextAnnotation({
140            text: watermarkText,
141            fontSize: 32,
142            textColor: appTheme.ForegroundColor,
143            x1: 0.5,
144            y1: 0.5,
145            opacity: 0.23,
146            horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
147            verticalAnchorPoint: EVerticalAnchorPoint.Center,
148            xCoordinateMode: ECoordinateMode.Relative,
149            yCoordinateMode: ECoordinateMode.Relative,
150            annotationLayer: EAnnotationLayer.BelowChart,
151        })
152    );
153
154    return { sciChartSurface, wasmContext };
155};
156

Realtime Percentage Change using Filter - Angular

Overview

This example demonstrates how to integrate SciChart.js with Angular for real-time data visualization. It focuses on converting series data into percentage change values by applying a dynamic ScaleOffsetFilter transformation and allows users to toggle between displaying the original data and the percentage change view.

Technical Implementation

The implementation initializes a SciChartSurface with numeric X and Y axes and adds two line series that use random walk data as their source. A custom renderable series is created by extending the default series class to provide enhanced tooltip information. The key part of the logic involves subscribing to axis changes to update the scale factor of the filter dynamically, ensuring that percentage changes are calculated in real-time. Detailed technical insights on custom series development can be found in the Custom RenderableSeries API.

Features and Capabilities

The example offers real-time data updates, dynamic percentage recalculations, and interactive features such as zooming and panning. It leverages Angular’s event handling to subscribe to axis range changes and apply corresponding transformations on the fly. Additionally, the sample emphasizes performance by updating only the necessary filter parameters, which optimizes rendering performance during continuous data updates. For further reading on real-time updates and performance optimization, refer to the Adding Realtime Updates documentation.

Integration and Best Practices

This example illustrates best practices for integrating SciChart.js into an Angular application. By utilizing component-based design and Angular’s robust event management system, developers can build charts that handle real-time data efficiently. Even though the source example originally demonstrates some concepts with React, the Angular integration follows a similar approach by using Angular-compatible toggle buttons and state management strategies. Developers interested in further Angular integrations should explore the scichart-angular package and review the Memory Best Practices to ensure efficient resource management in high-performance applications.

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