Demonstrates the DateTimeNumericAxis with 64-bit precision, handling ranges from Nanoseconds to Billions of Years.
drawExample.ts
index.tsx
theme.ts
createDatasets.ts
1import {
2 DateTimeNumericAxis,
3 EllipsePointMarker,
4 isRealNumber,
5 MouseWheelZoomModifier,
6 RubberBandXyZoomModifier,
7 ZoomExtentsModifier,
8 ZoomPanModifier,
9 XyDataSeries,
10 NumericAxis,
11 FastLineRenderableSeries,
12 SciChartSurface,
13 NumberRange,
14 EAutoRange,
15 EAxisAlignment,
16 EExecuteOn,
17 deleteSafe,
18 SmartDateLabelProvider,
19 EHighPrecisionLabelMode,
20 EDatePrecision,
21 formatNumber,
22 ENumericFormat,
23} from "scichart";
24import { TDatasetId, createDatasets } from "./createDatasets";
25import { getIndicesRange } from "scichart/Charting/Model/BaseDataSeries";
26import { appTheme } from "../../../theme";
27
28export const drawExample = async (rootElement: string | HTMLDivElement) => {
29 const { wasmContext, sciChartSurface } = await SciChartSurface.create(rootElement, {
30 theme: appTheme.SciChartJsTheme,
31 });
32
33 const xAxis = new DateTimeNumericAxis(wasmContext, {
34 axisAlignment: EAxisAlignment.Bottom,
35 useNativeText: true,
36 growBy: new NumberRange(0.05, 0.05),
37 labelProvider: new SmartDateLabelProvider({
38 datePrecision: EDatePrecision.Seconds,
39 highPrecisionLabelMode: EHighPrecisionLabelMode.Suffix,
40
41 showWiderDateOnFirstLabel: true,
42 showYearOnWiderDate: true,
43
44 showSecondsOnPreciseDate: true,
45 showSecondsOnWideDate: false,
46 }),
47 });
48
49 // Special handling for huge dates that do not fit in standard JS Date object
50 const sdlp = xAxis.labelProvider as SmartDateLabelProvider;
51 const YEAR = 86400 * 365.25;
52 const originalWideDateFormatter = sdlp.formatDateWide.bind(sdlp);
53 const originalPreciseDateFormatter = sdlp.formatDatePrecise.bind(sdlp);
54
55 sdlp.formatDateWide = (labelRange: string, valueInSeconds: number): string => {
56 // even with huge values, use k, m, b suffixes for thousands, millions, billions or years
57 if (valueInSeconds > YEAR * 9999) {
58 return "Year " + formatNumber(valueInSeconds / YEAR, ENumericFormat.Engineering, 1); // e.g. "Year 500M" -> year 500 million
59 }
60 return originalWideDateFormatter(labelRange, valueInSeconds);
61 };
62 sdlp.formatDatePrecise = (labelRange: string, valueInSeconds: number, rawValue?: number): string => {
63 if (valueInSeconds > YEAR * 9999) {
64 const cutTime = valueInSeconds % 86400; // a bit of a hack, since we can't format dates hours from year 500 Million :)
65 return originalPreciseDateFormatter(labelRange, cutTime, rawValue);
66 }
67 return originalPreciseDateFormatter(labelRange, valueInSeconds, rawValue);
68 };
69 sciChartSurface.xAxes.add(xAxis);
70
71 sciChartSurface.yAxes.add(
72 new NumericAxis(wasmContext, {
73 axisAlignment: EAxisAlignment.Left,
74 growBy: new NumberRange(0.1, 0.1),
75 labelPrecision: 3,
76 autoRange: EAutoRange.Always,
77 })
78 );
79
80 const datasets = createDatasets();
81 let currentDataset = datasets[3]; // the NanoSeconds one
82
83 const lineSeries = new FastLineRenderableSeries(wasmContext, {
84 dataSeries: new XyDataSeries(wasmContext, {
85 xValues: currentDataset.xValues,
86 yValues: currentDataset.yValues,
87 containsNaN: false,
88 isSorted: true,
89 }),
90 stroke: appTheme.VividOrange,
91 strokeThickness: 2,
92 pointMarker: new EllipsePointMarker(wasmContext, {
93 fill: appTheme.ForegroundColor,
94 }),
95 });
96
97 sciChartSurface.renderableSeries.add(lineSeries);
98
99 // Add modifiers
100 sciChartSurface.chartModifiers.add(
101 new MouseWheelZoomModifier(),
102 new ZoomPanModifier(),
103 new ZoomExtentsModifier(),
104 new RubberBandXyZoomModifier({ executeCondition: { button: EExecuteOn.MouseRightButton } })
105 );
106 sciChartSurface.zoomExtents();
107
108 return {
109 wasmContext,
110 sciChartSurface,
111 controls: {
112 zoomInPrecise: () => {
113 const clusterIndex = currentDataset.id === "secondPrecision" ? 2 : 15;
114 const pointsPerCluster = 10;
115
116 const dataSeries = lineSeries.dataSeries as XyDataSeries;
117 const xValues = dataSeries.getNativeXValues();
118
119 const startDataIndex = clusterIndex * pointsPerCluster;
120 const endDataIndex = startDataIndex + (pointsPerCluster - 1);
121
122 if (endDataIndex >= xValues.size()) return;
123
124 const minX = xValues.get(startDataIndex);
125 const maxX = xValues.get(endDataIndex);
126
127 let padding = 3;
128 xAxis.animateVisibleRange(
129 new NumberRange(minX - padding, maxX + padding),
130 3000,
131 (t) => 1 - Math.pow(1 - t, 10) // very exaggerated ease out :)
132 );
133 },
134 zoomOut: () => {
135 sciChartSurface.zoomExtents(2000);
136 },
137 setDataset: (id: TDatasetId) => {
138 const next = datasets.find((d) => d.id === id)!;
139 currentDataset = next;
140
141 const dataSeries = lineSeries.dataSeries as XyDataSeries;
142 dataSeries.clear();
143 dataSeries.appendRange(next.xValues, next.yValues);
144
145 const sdlp = xAxis.labelProvider as SmartDateLabelProvider;
146 switch (id) {
147 case "secondPrecision":
148 lineSeries.stroke = appTheme.VividOrange;
149 sdlp.datePrecision = EDatePrecision.Seconds;
150 sdlp.showSecondsOnPreciseDate = true;
151 break;
152 case "millisecondPrecision":
153 lineSeries.stroke = appTheme.VividPink;
154 sdlp.datePrecision = EDatePrecision.Milliseconds;
155 sdlp.showSecondsOnPreciseDate = false;
156 break;
157 case "microsecondPrecision":
158 lineSeries.stroke = appTheme.VividPurple;
159 sdlp.datePrecision = EDatePrecision.Microseconds;
160 sdlp.showSecondsOnPreciseDate = true;
161 break;
162 case "nanosecondPrecision":
163 lineSeries.stroke = appTheme.VividTeal;
164 sdlp.datePrecision = EDatePrecision.Nanoseconds;
165 sdlp.showSecondsOnPreciseDate = true;
166 break;
167 }
168
169 sciChartSurface.zoomExtents();
170 },
171 },
172 };
173};
174This example demonstrates the extreme precision capabilities of the DateTimeNumericAxis in SciChart.js within a React application.
Standard WebGL rendering and many JavaScript charting libraries are limited to 32-bit floating-point coordinates. This limitation typically causes rendering artifacts (jitter) or precision loss when dealing with very large numbers (like astronomical dates) or very small increments (like nanoseconds). SciChart.js utilizes a proprietary 64-bit floating-point coordinate pipeline to overcome this, allowing for visualization of data across vast timescales without loss of detail.
This demo allows you to toggle between four distinct datasets to showcase this flexibility:
Date object (which is limited to approx. 270,000 years).The SmartDateLabelProvider is key to this functionality. By setting the datePrecision property, we instruct the chart how to interpret the raw Float64 data:
EDatePrecision.Nanoseconds: Divides input by 1,000,000,000 to get seconds.EDatePrecision.Microseconds: Divides input by 1,000,000.Furthermore, the highPrecisionLabelMode allows formatting sub-millisecond data using:
Suffix (e.g., '50ns'),
Fractional (e.g., '.000000050')
Scientific (e.g., '5.0e-8') notation, ensuring labels remain readable even at maximum zoom depth.

Demonstrates Multiple X & Y Axis on a React Chart using SciChart.js. SciChart supports unlimited left, right, top, bottom X, Y axis with configurable alignment and individual zooming, panning

Demonstrates Secondary Y Axis on a React Chart using SciChart.js. SciChart supports unlimited, multiple left, right, top, bottom X, Y axis with configurable alignment and individual zooming, panning

Demonstrates how to Zoom, Scale or Pan individual Axis on a React Chart with SciChart.js AxisDragModifiers

Demonstrates how to zoom and pan a realtime React Chart while it is updating, with SciChart.js ZoomState API

Demonstrates how to use multiple Zoom and Pan Modifiers on a React Chart with SciChart.js

Demonstrates how to zoom and pan with an Overview Chart

shows how to load data on zoom/pan and how to create an overview chart for this case.

Explore SciChart's Polar Interactivity Modifiers including zooming, panning, and cursor tracking. Try the demo to trial the Polar Chart Behavior Modifiers.

Demonstrates how to build synchronized multi-panel charts with an overview range selector using SciChart.js in React