High Precision Date Axis

Demonstrates the DateTimeNumericAxis with 64-bit precision, handling ranges from Nanoseconds to Billions of Years.

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.tsx

theme.ts

createDatasets.ts

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

High Precision Date Axis Example - Angular

Overview

This 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.

The 4 Precision Ranges

This demo allows you to toggle between four distinct datasets to showcase this flexibility:

  • Nanosecond Precision: A range of 50 Days. Demonstrates extreme detail (1 unit = 1e-9 seconds). Suitable for high-frequency trading or scientific instrumentation.
  • Microsecond Precision: A range of 40 Years. (1 unit = 1e-6 seconds).
  • Millisecond Precision: A range of 70,000 Years. Standard Javascript Date precision, but pushed to historical limits.
  • Seconds Precision: A range of 1 Billion Years. Demonstrates handling values that far exceed the limits of the standard JavaScript Date object (which is limited to approx. 270,000 years).

Technical Implementation

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.

angular Chart Examples & Demos

See Also: Zoom and Pan a Chart (9 Demos)

Angular Chart with Multiple X Axes | SciChart.js Demo

Angular Chart with Multiple X Axes

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

Angular Chart with Secondary Y Axes | SciChart.js Demo

Angular Chart with Secondary Y Axes

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

Drag Angular Chart Axis to Scale or Pan | SciChart.js

Drag Angular Chart Axis to Scale or Pan

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

Zoom and Pan a Realtime Angular Chart | SciChart.js Demo

Zoom and Pan a Realtime Angular Chart

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

Zoom and Pan with Angular Chart multiple Modifiers | SciChart

Zoom and Pan with Angular Chart multiple Modifiers

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

Zoom and Pan with Overview Chart | Angular Charts | SciChart.js

Zoom and Pan with Overview Chart

Demonstrates how to zoom and pan with an Overview Chart

Virtualized Angular Charts: Load Data on Zoom/Pan | SciChart

Virtualized Angular Charts: Load Data on Zoom/Pan

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

Angular Polar Modifiers | Polar Interactivity Modifiers

Angular Polar Modifiers | Polar Interactivity Modifiers Demo

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

NEW!
Angular Overview for SubCharts with Range Selection

Angular Overview for SubCharts with Range Selection

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

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