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 MouseWheelZoomModifier,
5 RubberBandXyZoomModifier,
6 ZoomExtentsModifier,
7 ZoomPanModifier,
8 XyDataSeries,
9 NumericAxis,
10 FastLineRenderableSeries,
11 SciChartSurface,
12 NumberRange,
13 EAutoRange,
14 EAxisAlignment,
15 EExecuteOn,
16 SmartDateLabelProvider,
17 EHighPrecisionLabelMode,
18 EDatePrecision,
19 formatNumber,
20 ENumericFormat,
21} from "scichart";
22import { TDatasetId, createDatasets } from "./createDatasets";
23import { appTheme } from "../../../theme";
24
25export const drawExample = async (rootElement: string | HTMLDivElement) => {
26 const { wasmContext, sciChartSurface } = await SciChartSurface.create(rootElement, {
27 theme: appTheme.SciChartJsTheme,
28 });
29
30 const xAxis = new DateTimeNumericAxis(wasmContext, {
31 axisAlignment: EAxisAlignment.Bottom,
32 useNativeText: true,
33 growBy: new NumberRange(0.05, 0.05),
34 labelProvider: new SmartDateLabelProvider({
35 highPrecisionLabelMode: EHighPrecisionLabelMode.Suffix,
36 datePrecision: EDatePrecision.Nanoseconds,
37 // the default dataset is using nanosecond precision,
38 // this will be changed when switching datasets
39
40 showWiderDateOnFirstLabel: true,
41 showYearOnWiderDate: true,
42
43 showSecondsOnPreciseDate: true,
44 showSecondsOnWideDate: false,
45 }),
46 });
47
48 // Special handling for huge dates that do not fit in standard JS Date object
49 const sdlp = xAxis.labelProvider as SmartDateLabelProvider;
50 const YEAR = 86400 * 365.25;
51 const originalWideDateFormatter = sdlp.formatDateWide.bind(sdlp);
52 const originalPreciseDateFormatter = sdlp.formatDatePrecise.bind(sdlp);
53
54 sdlp.formatDateWide = (labelRange: string, valueInSeconds: number): string => {
55 // even with huge values, use k, m, b suffixes for thousands, millions, billions or years
56 if (valueInSeconds > YEAR * 9999) {
57 return "Year " + formatNumber(valueInSeconds / YEAR, ENumericFormat.Engineering, 1); // e.g. "Year 500M" -> year 500 million
58 }
59 return originalWideDateFormatter(labelRange, valueInSeconds);
60 };
61 sdlp.formatDatePrecise = (labelRange: string, valueInSeconds: number, rawValue?: number): string => {
62 if (valueInSeconds > YEAR * 9999) {
63 const cutTime = valueInSeconds % 86400; // a bit of a hack, since we can't format dates hours from year 500 Million :)
64 return originalPreciseDateFormatter(labelRange, cutTime, rawValue);
65 }
66 return originalPreciseDateFormatter(labelRange, valueInSeconds, rawValue);
67 };
68 sciChartSurface.xAxes.add(xAxis);
69
70 sciChartSurface.yAxes.add(
71 new NumericAxis(wasmContext, {
72 axisAlignment: EAxisAlignment.Left,
73 growBy: new NumberRange(0.1, 0.1),
74 labelPrecision: 3,
75 autoRange: EAutoRange.Always,
76 })
77 );
78
79 const lineSeries = new FastLineRenderableSeries(wasmContext, {
80 dataSeries: new XyDataSeries(wasmContext, {
81 containsNaN: false,
82 isSorted: true,
83 // x/y values will be appended when switching datasets, for now just create empty data series
84 }),
85 strokeThickness: 2,
86 pointMarker: new EllipsePointMarker(wasmContext, {
87 fill: appTheme.ForegroundColor
88 }),
89 });
90
91 sciChartSurface.renderableSeries.add(lineSeries);
92
93 // Add modifiers
94 sciChartSurface.chartModifiers.add(
95 new MouseWheelZoomModifier(),
96 new ZoomPanModifier(),
97 new ZoomExtentsModifier(),
98 new RubberBandXyZoomModifier({ executeCondition: { button: EExecuteOn.MouseRightButton } })
99 );
100 sciChartSurface.zoomExtents();
101
102 // Datasets handling
103 const datasets = createDatasets();
104
105 const useDataset = (id: TDatasetId) => {
106 const next = datasets.find((d) => d.id === id)!;
107 const dataSeries = lineSeries.dataSeries as XyDataSeries;
108 dataSeries.clear();
109 dataSeries.appendRange(next.xValues, next.yValues);
110
111 const sdlp = xAxis.labelProvider as SmartDateLabelProvider;
112 switch (id) {
113 case "secondPrecision":
114 lineSeries.stroke = appTheme.VividOrange;
115 sdlp.datePrecision = EDatePrecision.Seconds;
116 sdlp.showSecondsOnPreciseDate = true;
117 break;
118 case "millisecondPrecision":
119 lineSeries.stroke = appTheme.VividPink;
120 sdlp.datePrecision = EDatePrecision.Milliseconds;
121 sdlp.showSecondsOnPreciseDate = false;
122 break;
123 case "microsecondPrecision":
124 lineSeries.stroke = appTheme.VividPurple;
125 sdlp.datePrecision = EDatePrecision.Microseconds;
126 sdlp.showSecondsOnPreciseDate = true;
127 break;
128 case "nanosecondPrecision":
129 lineSeries.stroke = appTheme.VividTeal;
130 sdlp.datePrecision = EDatePrecision.Nanoseconds;
131 sdlp.showSecondsOnPreciseDate = true;
132 break;
133 }
134 sciChartSurface.zoomExtents();
135 }
136 useDataset("nanosecondPrecision"); // default to nanosecond precision
137
138 return {
139 wasmContext,
140 sciChartSurface,
141 controls: {
142 zoomInPrecise: () => {
143 const clusterIndex = 15; // on which cluster to zoom in
144 const pointsPerCluster = 10;
145
146 const dataSeries = lineSeries.dataSeries as XyDataSeries;
147 const xValues = dataSeries.getNativeXValues();
148
149 const startDataIndex = clusterIndex * pointsPerCluster;
150 const endDataIndex = startDataIndex + (pointsPerCluster - 1);
151
152 if (endDataIndex >= xValues.size()) return;
153
154 const minX = xValues.get(startDataIndex);
155 const maxX = xValues.get(endDataIndex);
156
157 let padding = 3;
158 xAxis.animateVisibleRange(
159 new NumberRange(minX - padding, maxX + padding),
160 3000,
161 (t) => 1 - Math.pow(1 - t, 10) // very exaggerated ease out :)
162 );
163 },
164 zoomOut: () => {
165 sciChartSurface.zoomExtents(2000);
166 },
167 useDataset
168 },
169 };
170};
171This example demonstrates the extreme precision capabilities of the DateTimeNumericAxis in SciChart.js within an Angular 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 Angular 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 Angular 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 Angular Chart with SciChart.js AxisDragModifiers

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

Demonstrates how to use multiple Zoom and Pan Modifiers on a Angular 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 Angular