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

vanilla.ts

theme.ts

createDatasets.ts

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

High Precision Date Axis Example - JavaScript

Overview

This example demonstrates the extreme precision capabilities of the DateTimeNumericAxis in SciChart.js.

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.

javascript Chart Examples & Demos

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

JavaScript Chart with Multiple X Axes | SciChart.js Demo

JavaScript Chart with Multiple X Axes

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

JavaScript Chart with Secondary Y Axes | SciChart.js Demo

JavaScript Chart with Secondary Y Axes

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

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

Drag JavaScript Chart Axis to Scale or Pan

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

Zoom and Pan a Realtime JavaScript Chart | SciChart.js

Zoom and Pan a Realtime JavaScript Chart

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

Zoom and Pan with JavaScript Chart multiple Modifiers

Zoom and Pan with JavaScript Chart multiple Modifiers

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

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

Zoom and Pan with Overview Chart

Demonstrates how to zoom and pan with an Overview Chart

Virtualized JavaScript Charts: Load Data on Zoom/Pan

Virtualized JavaScript Charts: Load Data on Zoom/Pan

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

JavaScript Polar Modifiers | Polar Interactivity Modifiers

JavaScript 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!
JavaScript Overview for SubCharts with Range Selection

JavaScript Overview for SubCharts with Range Selection

Demonstrates how to create multiple synchronized subcharts with an overview range selector using SciChart.js and SubSurfaces

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