Demonstrates how to add and use MetaData in a chart using SciChart.js, High Performance JavaScript Charts
drawExample.ts
index.tsx
theme.ts
1import { appTheme } from "../../../theme";
2
3import {
4 DataLabelState,
5 ECoordinateMode,
6 EHorizontalAnchorPoint,
7 EStrokePaletteMode,
8 IPointMetadata,
9 IPointMarkerPaletteProvider,
10 IRenderableSeries,
11 LineSeriesDataLabelProvider,
12 NumericAxis,
13 NumberRange,
14 parseColorToUIntArgb,
15 SciChartSurface,
16 SplineLineRenderableSeries,
17 TextAnnotation,
18 TPointMarkerArgb,
19 TWebAssemblyChart,
20 Thickness,
21 TSciChart,
22 XyDataSeries,
23 XySeriesInfo,
24 EllipsePointMarker,
25 RolloverModifier,
26} from "scichart";
27
28export const drawExample = async (rootElement: string | HTMLDivElement): Promise<TWebAssemblyChart> => {
29 // Create a chart with X, Y axis
30 const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
31 theme: appTheme.SciChartJsTheme,
32 });
33 sciChartSurface.xAxes.add(new NumericAxis(wasmContext));
34 sciChartSurface.yAxes.add(new NumericAxis(wasmContext, { growBy: new NumberRange(0.2, 0.2) }));
35
36 // Given a dataset with X, Y but also additional values in the form of an object of any kind
37 const dataValues = [
38 { x: 0, y: 50, anObject: { label: "", pointColor: "#F48420", isSelected: false } },
39 { x: 1, y: 35, anObject: { label: "Orange Point", pointColor: "#F48420", isSelected: false } },
40 { x: 2, y: 68, anObject: { label: "Highest Point", pointColor: "#7BCAAB", isSelected: false } },
41 { x: 3, y: 58, anObject: { label: "Selected Point", pointColor: "#F48420", isSelected: true } },
42 { x: 4, y: 50, anObject: { label: "Orange Point", pointColor: "#F48420", isSelected: false } },
43 { x: 5, y: 50, anObject: { label: "", pointColor: "#F48420", isSelected: false } },
44 { x: 6, y: 40, anObject: { label: "Blue Point", pointColor: "#50C7E0", isSelected: false } },
45 { x: 7, y: 53, anObject: { label: "Selected Point", pointColor: "#F48420", isSelected: true } },
46 { x: 8, y: 55, anObject: { label: "", pointColor: "#F48420", isSelected: false } },
47 { x: 9, y: 23, anObject: { label: "Blue Point", pointColor: "#50C7E0", isSelected: false } },
48 { x: 10, y: 45, anObject: { label: "Selected Point", pointColor: "#F48420", isSelected: true } },
49 { x: 11, y: 12, anObject: { label: "Lowest Point", pointColor: "#EC0F6C", isSelected: false } },
50 { x: 12, y: 59, anObject: { label: "", pointColor: "#F48420", isSelected: false } },
51 { x: 13, y: 60, anObject: { label: "", pointColor: "#F48420", isSelected: false } },
52 ];
53
54 // You can create a dataseries with these object values as metadata
55 const xyDataSeriesWithMetadata = new XyDataSeries(wasmContext, {
56 xValues: dataValues.map((row) => row.x),
57 yValues: dataValues.map((row) => row.y),
58 metadata: dataValues.map((row) => row.anObject), // put any javascript object here
59 });
60
61 // You can assign this dataseries to a RenderableSeries in SciChart
62 const lineSeries = new SplineLineRenderableSeries(wasmContext, {
63 dataSeries: xyDataSeriesWithMetadata,
64 stroke: appTheme.VividSkyBlue,
65 strokeThickness: 3,
66 pointMarker: new EllipsePointMarker(wasmContext, {
67 width: 15,
68 height: 15,
69 strokeThickness: 0,
70 }),
71 });
72
73 // Now you can consume metadata in the following ways
74 // - Colouring points
75 // - Labelling points
76 // - Custom data for tooltips
77 // - Tagging datapoints with the objects for later use
78 //
79
80 // 1. via paletteprovider (colour points or segments based on metadata values)
81
82 // @ts-ignore
83 const getColorFromMetadata = (metadata) => {
84 // @ts-ignore
85 const pointColorArgb = parseColorToUIntArgb(metadata.pointColor);
86 const selectedColorArgb = 0xffffffff;
87 const fill = metadata.isSelected ? selectedColorArgb : pointColorArgb;
88 return fill;
89 };
90
91 const pointPaletteProvider: IPointMarkerPaletteProvider = {
92 strokePaletteMode: EStrokePaletteMode.SOLID,
93 onAttached(parentSeries: IRenderableSeries): void {},
94 onDetached(): void {},
95 overridePointMarkerArgb(
96 xValue: number,
97 yValue: number,
98 index: number,
99 opacity?: number,
100 metadata?: IPointMetadata
101 ): TPointMarkerArgb {
102 // Metadata values can be used in paletteprovider overrides
103 if (metadata) {
104 const fill = getColorFromMetadata(metadata);
105 return { stroke: fill, fill };
106 }
107 return undefined; // means use default colour
108 },
109 };
110 lineSeries.paletteProvider = pointPaletteProvider;
111
112 // 2. Via DataLabel provider
113 const dataLabelProvider = new LineSeriesDataLabelProvider({
114 // @ts-ignore
115 metaDataSelector: (metadata) => metadata.label, // This is how you route a label (string) from metadata to data-labels in scichart
116 style: { fontFamily: "Arial", fontSize: 16, padding: new Thickness(5, 5, 5, 5) },
117 color: appTheme.ForegroundColor,
118 });
119 lineSeries.dataLabelProvider = dataLabelProvider;
120 // This is how you override colors of labels on a per-label basis, which can also come from metadata
121 dataLabelProvider.getColor = (state: DataLabelState, label: string) => {
122 const metadata = state.getMetaData();
123 return getColorFromMetadata(metadata);
124 };
125
126 // 3. Via cursors and tooltips
127 lineSeries.rolloverModifierProps.markerColor = appTheme.DarkIndigo;
128 lineSeries.rolloverModifierProps.tooltipColor = appTheme.Indigo;
129 lineSeries.rolloverModifierProps.tooltipDataTemplate = (seriesInfo: XySeriesInfo): string[] => {
130 const valuesWithLabels: string[] = [];
131 // Line Series
132 const xySeriesInfo = seriesInfo as XySeriesInfo;
133
134 valuesWithLabels.push("X Value: " + xySeriesInfo.formattedXValue);
135 valuesWithLabels.push("Y Value: " + xySeriesInfo.formattedYValue);
136
137 valuesWithLabels.push(" ");
138 if (seriesInfo.pointMetadata) {
139 // @ts-ignore
140 let label = seriesInfo.pointMetadata.label;
141 label = label === "" ? "..." : label;
142 valuesWithLabels.push(`Metadata Label: "${label}"`);
143 // @ts-ignore
144 valuesWithLabels.push("Metadata Selected: " + seriesInfo.pointMetadata.isSelected);
145 }
146 return valuesWithLabels;
147 };
148
149 sciChartSurface.renderableSeries.add(lineSeries);
150
151 // Add a RolloverModifier for tooltips
152 sciChartSurface.chartModifiers.add(
153 new RolloverModifier({
154 showRolloverLine: false,
155 showTooltip: true,
156 })
157 );
158
159 // Add title annotation
160 sciChartSurface.annotations.add(
161 new TextAnnotation({
162 text: "Line Chart with Metadata (Objects per data-point)",
163 fontSize: 18,
164 textColor: appTheme.ForegroundColor,
165 x1: 0.5,
166 y1: 0,
167 opacity: 0.77,
168 horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
169 xCoordinateMode: ECoordinateMode.Relative,
170 yCoordinateMode: ECoordinateMode.Relative,
171 })
172 );
173
174 sciChartSurface.zoomExtents();
175 return { sciChartSurface, wasmContext };
176};
177This example demonstrates how to integrate SciChart.js within an Angular application to render a high performance 2D chart. Each data point carries custom metadata that drives dynamic point coloring, advanced tooltips, and data labels. The example leverages asynchronous chart initialization along with WebAssembly rendering for optimal performance.
The chart is created asynchronously using SciChart.js's API where numeric axes, a spline line series, and annotations are programmatically configured. A data series is constructed by mapping raw X and Y values along with metadata - custom JavaScript objects containing properties which can drive label text, custom data-point color, and selection state. This metadata is then utilized in multiple ways: a custom PaletteProvider dynamically adjusts point marker colors based on metadata, a custom DataLabelProvider extracts labels directly from metadata for each point, and a RolloverModifier displays interactive tooltips that include metadata details. For additional details on implementing metadata-driven tooltips and data labels, refer to the Metadata and Tooltips documentation. The asynchronous initialization approach and Angular integration using ScichartAngularComponent is further detailed in the Getting Started with SciChart JS guide.
The example includes real-time interactive updating of point appearance based on metadata, custom point coloring using a PaletteProvider, and dynamic labeling via a DataLabelProvider. Interactive tooltips display extra information such as custom labels and selection status, enhancing user interaction. The implementation leverages WebAssembly for high performance rendering, ensuring that even with these advanced features the chart remains responsive. Developers can explore the customization options provided by the PaletteProvider API and further refine label behavior as described in Getting Labels from Metadata.
In Angular applications, managing the chart lifecycle is crucial. The example demonstrates efficient integration by initializing the chart asynchronously and ensuring proper disposal to prevent memory leaks. Performance enhancements are achieved through the use of WebAssembly and optimized rendering techniques outlined in the Performance Optimisation of JavaScript Applications & Charts guide. This approach emphasizes best practices for integrating complex, high performance charts in Angular environments while offering extensive customization through metadata.

Demonstrates Hit-Testing a Angular Chart - point and click on the chart and get feedback about what data-points were clicked

Demonstrates adding Tooltips on mouse-move to a Angular Chart with SciChart.js RolloverModifier

Demonstrates adding a Cursor (Crosshair) to a Angular Chart with SciChart.js CursorModifier

Demonstrates adding Tooltips at certain positions to a Angular Chart with SciChart.js VerticalSliceModifier

Demonstrates Hit-Testing a Angular Chart - point and click on the chart and get feedback about what data-points were clicked

Demonstrates the DatapointSelectionModifier, which provides a UI to select one or many data points, and works with DataPointSelectionPaletteProvider to change the appearance of selected points

Demonstrates how to customise the tooltips for Rollover, Cursor and VerticalSlice modifiers in an Angular Chart with SciChart.js