Datapoint Metadata Tooltips on JavaScript Chart

Demonstrates how to add and use MetaData in a chart using SciChart.js, High Performance JavaScript Charts

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.html

vanilla.ts

theme.ts

Copy to clipboard
Minimise
Fullscreen
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};
177

MetaData Labels, Tooltips and Rendering Example - JavaScript

Overview

This example, demonstrates how to create an interactive line chart using SciChart.js with JavaScript. It visualizes a dataset where each Xy data point is augmented with metadata that drives customizations such as point colors, dynamic labels, and interactive tooltips.

Technical Implementation

The chart is set up by asynchronously initializing a SciChartSurface with configured X and Y axes using the NumericAxis class and a defined growBy range via NumberRange. An XyDataSeries is created by mapping the provided X and Y values and attaching a metadata object (a custom JavaScript object) for each Xy data point. Customizations are applied through a custom PaletteProvider that adjusts the color of each point marker based on metadata. This is achieved using the helper function parseColorToUIntArgb for color conversion. Additionally, a custom DataLabelProvider extracts labels from metadata with a metaDataSelector, following concepts from Getting Labels from Metadata. A RolloverModifier is employed to provide interactive tooltips, enabling dynamic adjustments of marker and tooltip colors based on the underlying data. Text annotations are added using the TextAnnotation class, which supports relative coordinate modes for flexible placement.

Features and Capabilities

This example showcases metadata-driven customization where additional properties within each data point dictate not only the visual styling (such as point marker color via a custom palette provider) but also the data labels and tooltips. Such an approach allows each data point to be individually styled and can support features like highlighting or selection. Developers seeking to further understand the concepts can read about the DataSeries Metadata API here.

Integration and Best Practices

The implementation follows best practices for asynchronous initialization and resource cleanup in JavaScript, as shown by returning a destructor function that disposes of the SciChartSurface when no longer needed. This pattern is recommended in the Getting Started with SciChart JS guide. Although a React wrapper is provided in the project, the core implementation uses plain JavaScript, making it highly adaptable to various environments. By leveraging these techniques, developers can build highly interactive charts with a focus on performance and maintainability.

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