Angular Generic Animation

Demonstrates how to run Generic Animation using SciChart.js, High Performance JavaScript Charts

Fullscreen

Edit

 Edit

Docs

drawExample.ts

angular.ts

ExampleDataProvider.ts

theme.ts

Copy to clipboard
Minimise
Fullscreen
1import {
2    SciChartSurface,
3    NumericAxis,
4    NumberRange,
5    FastBubbleRenderableSeries,
6    XyzDataSeries,
7    EllipsePointMarker,
8    NativeTextAnnotation,
9    EVerticalAnchorPoint,
10    LineAnnotation,
11    GenericAnimation,
12} from "scichart";
13import { appTheme } from "../../../theme";
14import { fetchPopulationDataData } from "../../../ExampleData/ExampleDataProvider";
15
16const initializeChart = async (rootElement: string | HTMLDivElement) => {
17    // Create a SciChartSurface with bubble chart
18    const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
19        theme: appTheme.SciChartJsTheme,
20    });
21
22    sciChartSurface.title = "In SciChart.js you can animate anything";
23    sciChartSurface.titleStyle = {
24        placeWithinChart: true,
25        fontSize: 24,
26        color: appTheme.ForegroundColor + "C4",
27    };
28
29    sciChartSurface.xAxes.add(
30        new NumericAxis(wasmContext, {
31            axisTitle: "Year",
32            labelPrecision: 0,
33        })
34    );
35    sciChartSurface.yAxes.add(
36        new NumericAxis(wasmContext, {
37            axisTitle: "Life Expectancy (years)",
38            labelPrecision: 0,
39            growBy: new NumberRange(0, 0.2),
40        })
41    );
42
43    return { sciChartSurface, wasmContext };
44};
45
46export const drawExample = async (rootElement: string | HTMLDivElement) => {
47    const [chart, data] = await Promise.all([initializeChart(rootElement), fetchPopulationDataData()]);
48
49    const { sciChartSurface, wasmContext } = chart;
50
51    // TODO link to data source file
52    const { year, lifeExpectancy, gdpPerCapita, population } = data;
53
54    const bubbleSeries0 = new FastBubbleRenderableSeries(wasmContext, {
55        dataSeries: new XyzDataSeries(wasmContext, { xValues: year, yValues: lifeExpectancy, zValues: gdpPerCapita }),
56        opacity: 0.3,
57        // Set the default pointmarker size
58        pointMarker: new EllipsePointMarker(wasmContext, {
59            fill: appTheme.VividSkyBlue,
60            opacity: 0.3,
61            width: 64,
62            height: 64,
63            strokeThickness: 0,
64        }),
65        // z sizes are pixels so normalize these until the largest value in gdpPerCapita = 100px
66        zMultiplier: 100 / Math.max(...gdpPerCapita),
67    });
68    sciChartSurface.renderableSeries.add(bubbleSeries0);
69
70    // add a label & line
71    const labelAnnotation1 = new NativeTextAnnotation({
72        x1: 1955,
73        y1: 82,
74        text: "In this dataset life expectancy increases with time (years).\n Bubble size is GDP/capita",
75        fontSize: 18,
76        opacity: 0, // initially hidden
77        textColor: appTheme.PaleSkyBlue,
78        verticalAnchorPoint: EVerticalAnchorPoint.Bottom,
79    });
80    sciChartSurface.annotations.add(labelAnnotation1);
81    const lineAnnotation = new LineAnnotation({
82        x1: 1960,
83        y1: 81.5,
84        x2: 1966,
85        y2: 76,
86        opacity: 0, // initially hidden
87        stroke: appTheme.PaleSkyBlue,
88        strokeThickness: 2,
89    });
90    sciChartSurface.annotations.add(lineAnnotation);
91
92    // Add some animations using genericAnimation
93    //
94
95    // From 0..2 seconds typewrite the title
96    sciChartSurface.addAnimation(addTypewriterEffect(2000, 0, sciChartSurface));
97
98    // From 2..4 seconds animate the label on the data
99    sciChartSurface.addAnimation(
100        new GenericAnimation({
101            from: 0,
102            to: 1,
103            onAnimate: (from: number, to: number, progress: number) => {
104                labelAnnotation1.opacity = to * progress;
105                lineAnnotation.opacity = to * progress;
106            },
107            duration: 2000,
108            delay: 2000,
109        })
110    );
111
112    // From 5..8s change the data and relabel
113    //
114    const bubbleSeries1 = new FastBubbleRenderableSeries(wasmContext, {
115        dataSeries: new XyzDataSeries(wasmContext, {
116            xValues: gdpPerCapita,
117            yValues: lifeExpectancy,
118            zValues: population,
119        }),
120        opacity: 0.3,
121        // Set the default pointmarker size
122        pointMarker: new EllipsePointMarker(wasmContext, {
123            fill: appTheme.VividSkyBlue,
124            opacity: 0.3,
125            width: 64,
126            height: 64,
127            strokeThickness: 0,
128        }),
129        // z sizes are pixels so normalize these until the largest value in population = 100px
130        zMultiplier: 100 / Math.max(...population),
131        // initially hidden
132        isVisible: false,
133    });
134    sciChartSurface.renderableSeries.add(bubbleSeries1);
135
136    // Animate the new data
137    sciChartSurface.addAnimation(
138        new GenericAnimation({
139            from: 0,
140            to: 0.3,
141            onAnimate: (from: number, to: number, progress: number) => {
142                bubbleSeries1.isVisible = true;
143                bubbleSeries1.pointMarker.opacity = to * progress;
144                bubbleSeries0.pointMarker.opacity = 0.3 * (1 - progress);
145                labelAnnotation1.opacity = 1 - progress;
146                lineAnnotation.opacity = 1 - progress;
147            },
148            onCompleted: () => {
149                bubbleSeries0.isVisible = false;
150                // When the data has changed, now zoom to fit new data
151                sciChartSurface.xAxes.get(0).animateVisibleRange(new NumberRange(0, 50000), 1000);
152                sciChartSurface.xAxes.get(0).axisTitle = "GDP per capita";
153            },
154            duration: 3000,
155            delay: 5000,
156        })
157    );
158
159    // add a second label & line from 7..9s
160    const labelAnnotation2 = new NativeTextAnnotation({
161        x1: 10000,
162        y1: 50,
163        text: "Let's swap the axis to GDP vs. Life Expectancy using GenericAnimation.\n Bubble size is Population",
164        fontSize: 18,
165        opacity: 0, // initially hidden
166        textColor: appTheme.PaleSkyBlue,
167        verticalAnchorPoint: EVerticalAnchorPoint.Top,
168    });
169    sciChartSurface.annotations.add(labelAnnotation2);
170    const lineAnnotation2 = new LineAnnotation({
171        x1: 10000,
172        y1: 60,
173        x2: 20000,
174        y2: 50,
175        opacity: 0, // initially hidden
176        stroke: appTheme.PaleSkyBlue,
177        strokeThickness: 2,
178    });
179    sciChartSurface.annotations.add(lineAnnotation2);
180
181    // Animate the 2nd label and line
182    sciChartSurface.addAnimation(
183        new GenericAnimation({
184            from: 0,
185            to: 1,
186            onAnimate: (from: number, to: number, progress: number) => {
187                labelAnnotation2.opacity = to * progress;
188                lineAnnotation2.opacity = to * progress;
189            },
190            duration: 2000,
191            delay: 7000,
192        })
193    );
194
195    return { sciChartSurface };
196};
197
198const addTypewriterEffect = (duration: number, delay: number, sciChartSurface: SciChartSurface) => {
199    return new GenericAnimation<string>({
200        from: "",
201        to: sciChartSurface.title as string,
202        onAnimate: (from: string, to: string, progress: number) => {
203            const length = Math.floor(to.length * progress);
204            sciChartSurface.title = to.substring(0, length);
205        },
206        duration,
207        delay,
208        setInitialValueImmediately: true,
209    });
210};
211

Angular Generic Animation

Overview

This example demonstrates how to integrate SciChart.js into an Angular standalone component using the scichart-angular package. The "Generic Animation" example showcases how to animate various chart elements including the chart title, annotations, and data series. By leveraging asynchronous initialization and the powerful GenericAnimation class, developers can create dynamic, interactive charts that engage users with smooth animation transitions.

Technical Implementation

The implementation is centered around the asynchronous initialization of the SciChartSurface in an Angular component. The drawExample function sets up the chart by creating axes, bubble series, and annotations, then applies custom animations using the GenericAnimation class. One animation implements a typewriter effect to reveal the chart title, while others gradually fade in annotations and manage transitions between different bubble series. Developers can dive deeper into customizing these animations in the Generic Animations documentation. The asynchronous setup follows best practices outlined in Getting Started with SciChart JS and integrates seamlessly with Angular via the scichart-angular package.

Features and Capabilities

The example features several advanced capabilities including real-time update effects and dynamic annotation management. Notable features include:

  • A typewriter animation for the chart title that provides a step-by-step reveal.
  • Coordinated opacity transitions for annotations and bubble series to smoothly transition between different data states.
  • Dynamic updates of axis titles and visible ranges to reflect data series transitions. These features enable the creation of charts that are not only visually appealing but also highly interactive and responsive.

Integration and Best Practices

Integration into Angular is achieved through a standalone component that encapsulates the SciChart initialization and animation logic. This design approach ensures efficient lifecycle management and optimal performance. The timing and sequencing of animations are managed using precise delays and duration settings within the GenericAnimation instances, exemplifying best practices for handling dynamic animations in Angular. Further insights into similar animation techniques can be found in the Angular Startup Animation demo, while performance considerations are well documented in Performance Optimisation of JavaScript Applications & Charts.

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