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