Using VerticalSliceModifier

Demonstrates how to use tooltips at fixed positions using SciChart.js, High Performance JavaScript Charts

src/drawExample.ts
import { appTheme } from "./appTheme";
import { ExampleDataProvider } from "./ExampleDataProvider";
import {
    EllipsePointMarker,
    ENumericFormat,
    FastLineRenderableSeries,
    MouseWheelZoomModifier,
    NumberRange,
    NumericAxis,
    RolloverLegendSvgAnnotation,
    VerticalSliceModifier,
    SciChartSurface,
    XyDataSeries,
    ZoomExtentsModifier,
    ZoomPanModifier,
    SeriesInfo,
    ECoordinateMode,
    NativeTextAnnotation,
    EHorizontalAnchorPoint,
} from "scichart";

export const drawExample = async (rootElement: string | HTMLDivElement) => {
    // Create a SciChartSurface with X,Y Axis
    const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
        theme: appTheme.SciChartJsTheme,
    });
    sciChartSurface.xAxes.add(
        new NumericAxis(wasmContext, {
            growBy: new NumberRange(0.05, 0.05),
            labelFormat: ENumericFormat.Decimal,
            labelPrecision: 4,
        })
    );

    sciChartSurface.yAxes.add(
        new NumericAxis(wasmContext, {
            growBy: new NumberRange(0.1, 0.1),
            labelFormat: ENumericFormat.Decimal,
            labelPrecision: 4,
        })
    );

    // Add some data
    const data1 = ExampleDataProvider.getFourierSeriesZoomed(0.6, 0.13, 5.0, 5.15);
    const lineSeries0 = new FastLineRenderableSeries(wasmContext, {
        dataSeries: new XyDataSeries(wasmContext, {
            xValues: data1.xValues,
            yValues: data1.yValues,
            dataSeriesName: "First Line Series",
        }),
        strokeThickness: 3,
        stroke: appTheme.VividSkyBlue,
        pointMarker: new EllipsePointMarker(wasmContext, {
            width: 7,
            height: 7,
            strokeThickness: 0,
            fill: appTheme.VividSkyBlue,
        }),
    });
    sciChartSurface.renderableSeries.add(lineSeries0);

    const data2 = ExampleDataProvider.getFourierSeriesZoomed(0.5, 0.12, 5.0, 5.15);
    const lineSeries1 = new FastLineRenderableSeries(wasmContext, {
        dataSeries: new XyDataSeries(wasmContext, {
            xValues: data2.xValues,
            yValues: data2.yValues,
            dataSeriesName: "Second Line Series",
        }),
        strokeThickness: 3,
        stroke: appTheme.VividOrange,
        pointMarker: new EllipsePointMarker(wasmContext, {
            width: 7,
            height: 7,
            strokeThickness: 0,
            fill: appTheme.VividOrange,
        }),
    });
    sciChartSurface.renderableSeries.add(lineSeries1);

    const data3 = ExampleDataProvider.getFourierSeriesZoomed(0.4, 0.11, 5.0, 5.15);
    const lineSeries2 = new FastLineRenderableSeries(wasmContext, {
        dataSeries: new XyDataSeries(wasmContext, {
            xValues: data3.xValues,
            yValues: data3.yValues,
            dataSeriesName: "Third Line Series",
        }),
        strokeThickness: 3,
        stroke: appTheme.MutedPink,
        pointMarker: new EllipsePointMarker(wasmContext, {
            width: 7,
            height: 7,
            strokeThickness: 0,
            fill: appTheme.MutedPink,
        }),
    });
    sciChartSurface.renderableSeries.add(lineSeries2);

    // Here is where we add rollover tooltip behaviour
    //
    const vSlice1 = new VerticalSliceModifier({
        x1: 5.06,
        xCoordinateMode: ECoordinateMode.DataValue,
        isDraggable: true,
        // Defines if rollover vertical line is shown
        showRolloverLine: true,
        rolloverLineStrokeThickness: 1,
        rolloverLineStroke: appTheme.VividGreen,
        lineSelectionColor: appTheme.VividGreen,
        // Shows the default tooltip
        showTooltip: true,
        // Optional: Overrides the legend template to display additional info top-left of the chart
        tooltipLegendTemplate: getTooltipLegendTemplate,
        // Optional: Overrides the content of the tooltip
        tooltipDataTemplate: getTooltipDataTemplate,
    });
    const vSlice2 = new VerticalSliceModifier({
        x1: 0.75,
        xCoordinateMode: ECoordinateMode.Relative,
        isDraggable: true,
        // Defines if rollover vertical line is shown
        showRolloverLine: true,
        rolloverLineStrokeThickness: 1,
        rolloverLineStroke: appTheme.VividOrange,
        lineSelectionColor: appTheme.VividOrange,
        // Shows the default tooltip
        showTooltip: true,
        // Optional: Overrides the content of the tooltip
        tooltipDataTemplate: getTooltipDataTemplate,
    });
    sciChartSurface.chartModifiers.add(vSlice1, vSlice2);

    // Optional: Additional customisation may be done per-series, e.g.
    //
    lineSeries0.rolloverModifierProps.tooltipTextColor = appTheme.DarkIndigo;
    lineSeries2.rolloverModifierProps.tooltipColor = appTheme.VividPink;

    const textAnn1 = new NativeTextAnnotation({
        text: "xCoordinateMode: DataValue\nMoves with data\nLinked to Legend\nDraggable",
        textColor: appTheme.ForegroundColor,
        y1: 0.88,
        xCoordinateMode: ECoordinateMode.Pixel,
        yCoordinateMode: ECoordinateMode.Relative,
        horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
    });
    // Link the annotation position with the verticalSlice
    sciChartSurface.layoutMeasured.subscribe((data) => {
        textAnn1.x1 = vSlice1.verticalLine.x1;
    });
    sciChartSurface.annotations.add(textAnn1);

    const textAnn2 = new NativeTextAnnotation({
        text: "xCoordinateMode: Relative\nFixed position\nDraggable ",
        textColor: appTheme.ForegroundColor,
        y1: 0.88,
        xCoordinateMode: ECoordinateMode.Pixel,
        yCoordinateMode: ECoordinateMode.Relative,
        horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
    });
    sciChartSurface.layoutMeasured.subscribe((data) => {
        textAnn2.x1 = vSlice2.verticalLine.x1;
    });
    sciChartSurface.annotations.add(textAnn2);

    // Add further zooming and panning behaviours
    sciChartSurface.chartModifiers.add(new ZoomPanModifier({ enableZoom: true }));
    sciChartSurface.chartModifiers.add(new ZoomExtentsModifier());
    sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier());

    sciChartSurface.zoomExtents();
    return { sciChartSurface, wasmContext };
};

const getTooltipDataTemplate = (
    seriesInfo: SeriesInfo,
    tooltipTitle: string,
    tooltipLabelX: string,
    tooltipLabelY: string
) => {
    // Lines here are returned to the tooltip and displayed as text-line per tooltip
    const lines: string[] = [];
    lines.push(tooltipTitle);
    lines.push(`x: ${seriesInfo.formattedXValue}`);
    lines.push(`y: ${seriesInfo.formattedYValue}`);
    return lines;
};

// Override the standard tooltip displayed by CursorModifier
const getTooltipLegendTemplate = (seriesInfos: SeriesInfo[], svgAnnotation: RolloverLegendSvgAnnotation) => {
    let outputSvgString = "";

    // Foreach series there will be a seriesInfo supplied by SciChart. This contains info about the series under the house
    seriesInfos.forEach((seriesInfo, index) => {
        if (seriesInfo.isWithinDataBounds) {
            const lineHeight = 30;
            const y = 50 + index * lineHeight;
            // Use the series stroke for legend text colour
            const textColor = seriesInfo.stroke;
            // Use the seriesInfo formattedX/YValue for text on the
            outputSvgString += `<text x="8" y="${y}" font-size="16" font-family="Verdana" fill="${textColor}">
                                    ${seriesInfo.seriesName}: X=${seriesInfo.formattedXValue}, Y=${seriesInfo.formattedYValue}
                                </text>`;
        }
    });

    // Content here is returned for the custom legend placed in top-left of the chart
    return `<svg width="100%" height="100%">
                <text x="8" y="20" font-size="17" font-weight="bold" font-family="Verdana" fill="${appTheme.ForegroundColor}">Custom Rollover Legend</text>
                ${outputSvgString}
            </svg>`;
};

Using Vertical Slice Modifier (JavaScript)

Overview

This example demonstrates how to integrate SciChart.js into a JavaScript application using a Vertical Slice Modifier to enhance rollover interactivity. The chart is created by instantiating a SciChartSurface with NumericAxis and three FastLineRenderableSeries populated with Fourier series data. It then adds two VerticalSliceModifier tools that support custom tooltip templates and dynamic annotations, providing a rich interactive experience.

Technical Implementation

The core implementation is found in the drawExample module. Here, the chart is created using the standard SciChart.js API, without relying on any frameworks. Axes are defined with specific number ranges and label formats, and the FastLineRenderableSeries is used to render high performance line series data. The example leverages the VerticalSliceModifier to enable rollover tooltips and interactive vertical slice behavior by configuring properties such as xCoordinateMode, isDraggable, and tooltip templates which are customized by functions like getTooltipDataTemplate and getTooltipLegendTemplate. Additionally, dynamic updates are implemented via preRender event subscriptions that reposition NativeTextAnnotations to follow the vertical slice. For further details on custom tooltip templates, refer to Using Rollover Modifier Tooltips.

Features and Capabilities

The example showcases several advanced features of SciChart.js including:

  • Custom Tooltip Templates: The default tooltips provided by the VerticalSliceModifier are overridden using custom functions, enabling detailed, formatted information display during rollover interactions.

  • Coordinate Modes: By using different values for ECoordinateMode (such as DataValue and Relative), the example demonstrates how to position modifiers and annotations precisely.

  • High Performance Rendering: Employing FastLineRenderableSeries together with the performance benefits of the WASM context highlights best practices for handling large and complex datasets. For performance optimization tips, see Performance Tips & Tricks.

  • Interactive Modifiers: In addition to the Vertical Slice Modifier, other chart modifiers like ZoomPanModifier, ZoomExtentsModifier, and MouseWheelZoomModifier are added to grant users comprehensive navigation capabilities.

  • Resource Cleanup: The vanilla implementation shows a destructor pattern to properly dispose of chart resources when no longer needed, ensuring efficient memory management. This approach is discussed in various resource cleanup guidelines provided in SciChart documentation and related best practices.

Integration and Best Practices

This example is built entirely using JavaScript, demonstrating that SciChart.js can be integrated without additional frameworks. The minimal setup involves simply importing the drawExample module and invoking it with a target DOM element. Best practices include proper resource cleanup via a destructor function and the use of event subscriptions (such as preRender) for dynamic UI updates. Developers interested in integrating SciChart.js into non-framework scenarios can refer to the Tutorial 01 - Including SciChart.js in an HTML Page using CDN and Getting Started with SciChart JS.

By following these patterns and leveraging built-in features such as custom tooltips, precise coordinate modes, and fast rendering techniques, the example provides a robust template for creating highly interactive and performance-optimized charts in JavaScript.