JavaScript Chart Hit-Test API

Demonstrates how to add Hit-Test on click behavior to a chart using SciChart.js, High Performance JavaScript Charts

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.tsx

theme.ts

visualizeHitTest.ts

Copy to clipboard
Minimise
Fullscreen
1import { appTheme } from "../../../theme";
2import { visualiseHitTestPoint } from "./visualizeHitTest";
3
4import {
5    SciChartSurface,
6    NumericAxis,
7    EAxisAlignment,
8    NumberRange,
9    FastLineRenderableSeries,
10    XyDataSeries,
11    EllipsePointMarker,
12    HitTestInfo,
13    DpiHelper,
14    TextAnnotation,
15    EHorizontalAnchorPoint,
16    EVerticalAnchorPoint,
17    ECoordinateMode,
18    EAnnotationLayer,
19    EMultiLineAlignment,
20    ETextAlignment,
21    Thickness,
22    NativeTextAnnotation,
23} from "scichart";
24
25// This method hit-tests the series body
26export const HIT_TEST = "hitTest";
27// This method hit-tests the nearest data-point
28export const HIT_TEST_DATAPOINT = "hitTestDataPoint";
29// This method hit-tests by searching first in X, then Y
30export const HIT_TEST_X_SLICE = "hitTestXSlice";
31
32export const drawExample = async (rootElement: string | HTMLDivElement) => {
33    // Which hit-test method are we using? See below for usage
34    let whichHitTestMethod = HIT_TEST_DATAPOINT;
35
36    // Create a SciChartSurface with theme
37    const { wasmContext, sciChartSurface } = await SciChartSurface.create(rootElement, {
38        theme: appTheme.SciChartJsTheme,
39        title: [
40            "Click on the chart to demonstrate Hit-Test API",
41            "Change the Hit-Test method above to see the different behaviours",
42        ],
43        titleStyle: {
44            fontSize: 16,
45            placeWithinChart: true,
46            alignment: ETextAlignment.Left,
47            multilineAlignment: EMultiLineAlignment.Left,
48            color: appTheme.ForegroundColor + "C4",
49            padding: Thickness.fromString("13 4 0 9"),
50        },
51    });
52
53    // add an event listener for mouse down. You can access the actual SciChartSurface canvas as
54    // follows
55    sciChartSurface.domCanvas2D.addEventListener("mousedown", (mouseEvent) => {
56        // Translate the point to the series viewrect before hit-testing
57        // Attention!
58        // We need to multiply it by DpiHelper.PIXEL_RATIO
59        // DpiHelper.PIXEL_RATIO is used for High DPI and Retina screen support and also for the browser scaling
60        const mousePointX = mouseEvent.offsetX * DpiHelper.PIXEL_RATIO;
61        const mousePointY = mouseEvent.offsetY * DpiHelper.PIXEL_RATIO;
62        // const translatedPoint = translateFromCanvasToSeriesViewRect(mousePoint, sciChartSurface.seriesViewRect);
63        const HIT_TEST_RADIUS = 10 * DpiHelper.PIXEL_RATIO;
64
65        // call renderableSeries.hitTestProvider.hitTest passing in the mouse point
66        // other parameters determine the type of hit-test operation to perform
67        // There are three hit-test methods which have different outcomes. We let the user choose
68        let hitTestInfo: HitTestInfo;
69        if (whichHitTestMethod === HIT_TEST_DATAPOINT) {
70            // Hit-test the nearest data-point, searching first in X, then Y
71            hitTestInfo = lineSeries.hitTestProvider.hitTestDataPoint(mousePointX, mousePointY, HIT_TEST_RADIUS);
72        }
73        if (whichHitTestMethod === HIT_TEST_X_SLICE) {
74            // Hit-test the nearest data-point in X only (imagine a vertical slice on the chart)
75            hitTestInfo = lineSeries.hitTestProvider.hitTestXSlice(mousePointX, mousePointY, HIT_TEST_RADIUS);
76        }
77        if (whichHitTestMethod === HIT_TEST) {
78            // Hit-test in two-dimensions (slowest method but finds the nearest data-point by distance)
79            hitTestInfo = lineSeries.hitTestProvider.hitTest(mousePointX, mousePointY, HIT_TEST_RADIUS);
80        }
81
82        // Log the result to console. HitTestInfo contains information about the hit-test operation
83        console.log(
84            `${hitTestInfo.seriesName} hit test result (${whichHitTestMethod}):\r\n` +
85                ` MouseCoord=(${mousePointX}, ${mousePointY})\r\n` +
86                ` Hit-Test Coord=(${hitTestInfo.xCoord}, ${hitTestInfo.yCoord})\r\n` +
87                ` IsHit? ${hitTestInfo.isHit}\r\n` +
88                ` Result=(${hitTestInfo.xValue}, ${hitTestInfo.yValue}) `
89        );
90        visualiseHitTestPoint(sciChartSurface, hitTestInfo, whichHitTestMethod, 1000);
91    });
92
93    // Continue chart setup
94    //
95
96    // Create an X,Y Axis. For this example we put y-axis on the left to demonstrate offsetting the mouse-point when hit-testing
97    sciChartSurface.xAxes.add(new NumericAxis(wasmContext, { growBy: new NumberRange(0.1, 0.1) }));
98    sciChartSurface.yAxes.add(
99        new NumericAxis(wasmContext, {
100            axisAlignment: EAxisAlignment.Left,
101            growBy: new NumberRange(0.1, 0.1),
102        })
103    );
104
105    // Create a Line Series with XyDataSeries and some data
106    const lineSeries = new FastLineRenderableSeries(wasmContext, {
107        strokeThickness: 3,
108        stroke: appTheme.VividSkyBlue,
109        dataSeries: new XyDataSeries(wasmContext, {
110            dataSeriesName: "Line Series",
111            xValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
112            yValues: [0, 1, 5, 1, 20, 5, 1, 8, 9, 3],
113        }),
114        pointMarker: new EllipsePointMarker(wasmContext, {
115            stroke: appTheme.VividSkyBlue,
116            fill: appTheme.VividSkyBlue + "33",
117            width: 11,
118            height: 11,
119        }),
120    });
121
122    // Add the line series to the SciChartSurface
123    sciChartSurface.renderableSeries.add(lineSeries);
124
125    const watermarkAnnotation = (text: string = "") => {
126        return new NativeTextAnnotation({
127            text,
128            fontSize: 32,
129            textColor: appTheme.ForegroundColor,
130            x1: 0.5,
131            y1: 0.5,
132            opacity: 0.23,
133            horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
134            verticalAnchorPoint: EVerticalAnchorPoint.Center,
135            xCoordinateMode: ECoordinateMode.Relative,
136            yCoordinateMode: ECoordinateMode.Relative,
137            annotationLayer: EAnnotationLayer.BelowChart,
138        });
139    };
140
141    // Add a watermark
142    const theWatermark = watermarkAnnotation("METHOD: " + whichHitTestMethod + "()");
143    sciChartSurface.annotations.add(theWatermark);
144
145    // Allow changing method and updating watermark.
146    const updateHitTestMethod = (hitTestMethod: string) => {
147        console.log("Setting hitTestMethod " + hitTestMethod);
148        whichHitTestMethod = hitTestMethod;
149        theWatermark.text = "METHOD: " + hitTestMethod + "()";
150    };
151
152    return { sciChartSurface, wasmContext, controls: { updateHitTestMethod } };
153};
154

Hit Test API Example (JavaScript)

Overview

This example demonstrates the advanced hit testing functionality provided by SciChart.js using JavaScript. It enables users to click on the chart to evaluate different hit test methods such as series.hitTestProvider.hitTestDataPoint, hitTestXSlice, and hitTest. The resulting HitTestInfo is then visualised using temporary scatter series and animated annotations.

Technical Implementation

The implementation begins by configuring a SciChartSurface with a custom theme and title settings. It installs a mousedown event listener directly onto the canvas to capture click events. The event coordinates are adjusted using DpiHelper.PIXEL_RATIO to ensure correct mapping on high DPI and retina displays. Based on the chosen hit test method, the corresponding method from the RenderableSeries Hit-Test API is invoked to determine if the mouse position targets a data point or line segment.

Features and Capabilities

  • Interactive Hit Testing: Switchable methods allow testing with different approaches such as hitTestDataPoint, which finds the nearest data point, hitTestXSlice, which focuses on vertical slices of the chart or hitTest which can find the series body.
  • Visual Feedback and Annotations: The example makes use of dynamic annotations like TextAnnotation and LineAnnotation to visually indicate hit test results, highlighting successes with messages like Hit! or miss....
  • Smooth Animations: Animations are implemented using FadeAnimation and GenericAnimation to ensure that annotations appear and disappear smoothly.

Integration and Best Practices

This example follows best practices for integrating event listeners with the SciChartSurface canvas in JavaScript. It carefully converts mouse event coordinates to chart coordinates, a technique detailed in guides on mouse event coordinate conversion. Additionally, performance is optimized by choosing the most appropriate hit test method depending on the scenario, a concept further explored in the Performance Tips & Tricks documentation.

Overall, the example provides a comprehensive demonstration of SciChart.js capabilities for interactive and animated hit testing—delivering high-performance charting without relying on additional frameworks. Developers looking to build similar interactive charts in JavaScript can refer to the linked documentation for deeper technical insights.

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