DiscontinuousDateAxis Comparison with Javascript

Compares the features of the new DiscontinuousDateAxis to Numeric and Category Axis in SciChart.js, High Performance JavaScript Charts. This axis can collapse gaps like a category axis, but still allow varying point counts and multiple points at the same x value.

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.tsx

AxisSynchroniser.ts

theme.ts

Copy to clipboard
Minimise
Fullscreen
1import {
2    CategoryAxis,
3    DiscontinuousDateAxis,
4    ENumericFormat,
5    EXyDirection,
6    EllipsePointMarker,
7    FastCandlestickRenderableSeries,
8    FastLineRenderableSeries,
9    MouseWheelZoomModifier,
10    NumberRange,
11    NumericAxis,
12    NumericLabelProvider,
13    OhlcDataSeries,
14    RolloverModifier,
15    SciChartSurface,
16    XyDataSeries,
17    XyScatterRenderableSeries,
18    ZoomExtentsModifier,
19    ZoomPanModifier,
20} from "scichart";
21import { appTheme } from "../../../theme";
22
23// Custom label provider for days of the week
24class DayOfWeekLabelProvider extends NumericLabelProvider {
25    private dayNames = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
26
27    public get formatLabel() {
28        return (dataValue: number): string => {
29            if (dataValue > 100) {
30                const date = new Date(dataValue * 1000);
31                const day = date.getUTCDay();
32
33                return `${this.dayNames[day]} ${date.getUTCDate()}`;
34            } else {
35                return `${this.dayNames[dataValue % 7]} ${dataValue}`;
36            }
37        };
38    }
39}
40
41// Helper function to create data series
42const createDataSeries = (wasmContext: any, isCategoryAxis: boolean) => {
43    // X values from the first series are used as baseXValues for the DiscontinuousDate axis, unless you specify them explicitly.
44    const startDate = new Date(Date.UTC(2024, 0, 6, 0, 0, 0, 0));
45    const startTime = startDate.getTime() / 1000;
46    const ohlcSeries = new OhlcDataSeries(wasmContext, {
47        containsNaN: false,
48        isSorted: true,
49        xValues: [1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 15, 16].map((x) => startTime + x * 24 * 60 * 60),
50        openValues: [2, 5, 4, 6.2, 3, 3, 2.3, 3, 4, 5, 3, 3],
51        highValues: [4.2, 7.5, 6.8, 8.5, 5.5, 5.2, 4.8, 5.7, 6.9, 7.5, 5.8, 6.2],
52        lowValues: [0.8, 3.0, 2.0, 4.5, 1.0, 1.2, 0.5, 1.5, 2.5, 3.5, 1.5, 1.0],
53        closeValues: [3.5, 3.8, 6.0, 8.0, 2.0, 4.5, 1.2, 5.0, 6.2, 4.0, 5.0, 2.5],
54    });
55
56    // DiscontinuousDate axis supports data with values at the same x coordinate, and data in between baseValues
57    const dataSeries1 = new XyDataSeries(wasmContext, {
58        containsNaN: false,
59        isSorted: true,
60        xValues: [1, 2, 2, 5, 5.5, 8, 9, 9.5, 9.8, 11, 15, 16].map((x) => startTime + x * 24 * 60 * 60),
61        yValues: [2, 5, 4, 6.2, 3, 3, 2.3, 3, 4, 5, 3, 3],
62    });
63    if (!isCategoryAxis) {
64        dataSeries1.appendRange(
65            [5, 5, 9, 9, 15, 15].map((x) => startTime + x * 24 * 60 * 60),
66            [3, 4, 4, 5.5, 4.5, 1]
67        );
68    }
69
70    // DiscontinuousDate axis supports data with more or less x values than the baseValues
71    const dataSeries2 = new XyDataSeries(wasmContext, {
72        containsNaN: false,
73        isSorted: true,
74        xValues: [1, 3, 5, 8, 11, 16].map((x) => startTime + x * 24 * 60 * 60),
75        yValues: [3, 6, 5, 7.21, 4, 4],
76    });
77
78    return { ohlcSeries, dataSeries1, dataSeries2 };
79};
80
81// Helper function to add series to a chart
82const addSeriesToChart = (sciChartSurface: SciChartSurface, wasmContext: any, dataSeries: any) => {
83    sciChartSurface.renderableSeries.add(
84        new FastCandlestickRenderableSeries(wasmContext, {
85            dataSeries: dataSeries.ohlcSeries,
86            strokeThickness: 1,
87            brushUp: appTheme.VividGreen + "77",
88            brushDown: appTheme.MutedRed + "77",
89            strokeUp: appTheme.VividGreen,
90            strokeDown: appTheme.MutedRed,
91        })
92    );
93
94    sciChartSurface.renderableSeries.add(
95        new XyScatterRenderableSeries(wasmContext, {
96            dataSeries: dataSeries.dataSeries1,
97            stroke: appTheme.VividRed,
98            pointMarker: new EllipsePointMarker(wasmContext, {
99                width: 10,
100                height: 10,
101                fill: appTheme.VividRed,
102                strokeThickness: 0,
103                opacity: 0.8,
104            }),
105        })
106    );
107
108    sciChartSurface.renderableSeries.add(
109        new FastLineRenderableSeries(wasmContext, {
110            dataSeries: dataSeries.dataSeries2,
111            stroke: appTheme.VividSkyBlue,
112            opacity: 0.7,
113            strokeThickness: 4,
114            pointMarker: new EllipsePointMarker(wasmContext, {
115                width: 8,
116                height: 8,
117                fill: appTheme.VividSkyBlue,
118                strokeThickness: 0,
119                opacity: 0.7,
120            }),
121        })
122    );
123};
124
125// Create Discontinuous Date Axis Chart
126export const createDiscontinuousDateChart =
127    (customSettings: boolean) => async (rootElement: string | HTMLDivElement) => {
128        const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
129            theme: {
130                ...appTheme.SciChartJsTheme,
131                majorGridLineBrush: appTheme.MutedSkyBlue + "55",
132                minorGridLineBrush: appTheme.MutedSkyBlue + "22",
133            },
134        });
135
136        const xAxisDiscontinuous = new DiscontinuousDateAxis(wasmContext, {
137            growBy: new NumberRange(0.05, 0.05),
138            dataGap: 24 * 60 * 60, // This is auto-calculated using the minimum gap between baseXValues, but should be set where possible to avoid that calculation.
139            cursorLabelFormat: ENumericFormat.Date_DDMMHHMM,
140            axisTitle: "Discontinuous Date X Axis - Fixed gap between baseValues.  Ideal for financial data.",
141            axisTitleStyle: {
142                fontSize: 16,
143            },
144        });
145        if (customSettings) {
146            xAxisDiscontinuous.labelProvider = new DayOfWeekLabelProvider({
147                cursorLabelFormat: ENumericFormat.Date_DDMMHHMM,
148            });
149            xAxisDiscontinuous.autoTicks = false;
150            xAxisDiscontinuous.majorDelta = 24 * 60 * 60;
151            xAxisDiscontinuous.minorDelta = 4 * 60 * 60;
152        }
153
154        const yAxisLinear = new NumericAxis(wasmContext, {
155            labelFormat: ENumericFormat.Decimal,
156            labelPrecision: 2,
157            drawMinorGridLines: false,
158            growBy: new NumberRange(0.1, 0.1),
159        });
160
161        sciChartSurface.xAxes.add(xAxisDiscontinuous);
162        sciChartSurface.yAxes.add(yAxisLinear);
163
164        const dataSeries = createDataSeries(wasmContext, false);
165        addSeriesToChart(sciChartSurface, wasmContext, dataSeries);
166
167        sciChartSurface.chartModifiers.add(
168            new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection }),
169            new ZoomExtentsModifier(),
170            new ZoomPanModifier(),
171            new RolloverModifier({ showTooltip: false, showAxisLabel: true, modifierGroup: "Group1" })
172        );
173
174        sciChartSurface.zoomExtents();
175        return { sciChartSurface, wasmContext };
176    };
177
178// Create Numeric Axis Chart
179export const createNumericChart = (customSettings: boolean) => async (rootElement: string | HTMLDivElement) => {
180    const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
181        theme: {
182            ...appTheme.SciChartJsTheme,
183            majorGridLineBrush: appTheme.MutedSkyBlue + "55",
184            minorGridLineBrush: appTheme.MutedSkyBlue + "22",
185        },
186    });
187
188    const xAxisNumeric = new NumericAxis(wasmContext, {
189        labelFormat: ENumericFormat.Date_DDMM,
190        axisTitle: "Numeric X Axis - Cannot hide gaps",
191        axisTitleStyle: {
192            fontSize: 16,
193        },
194    });
195    if (customSettings) {
196        xAxisNumeric.labelProvider = new DayOfWeekLabelProvider({ cursorLabelFormat: ENumericFormat.Date_DDMMHHMM });
197        xAxisNumeric.autoTicks = false;
198        xAxisNumeric.majorDelta = 24 * 60 * 60;
199        xAxisNumeric.minorDelta = 4 * 60 * 60;
200    }
201
202    const yAxisLinear = new NumericAxis(wasmContext, {
203        labelFormat: ENumericFormat.Decimal,
204        labelPrecision: 2,
205        drawMinorGridLines: false,
206        growBy: new NumberRange(0.1, 0.1),
207    });
208
209    sciChartSurface.xAxes.add(xAxisNumeric);
210    sciChartSurface.yAxes.add(yAxisLinear);
211
212    const dataSeries = createDataSeries(wasmContext, false);
213    addSeriesToChart(sciChartSurface, wasmContext, dataSeries);
214
215    sciChartSurface.chartModifiers.add(
216        new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection }),
217        new ZoomExtentsModifier(),
218        new ZoomPanModifier(),
219        new RolloverModifier({ showTooltip: false, showAxisLabel: true, modifierGroup: "Group1" })
220    );
221    sciChartSurface.zoomExtents();
222    return { sciChartSurface, wasmContext };
223};
224
225// Create Category Axis Chart
226export const createCategoryChart = (customSettings: boolean) => async (rootElement: string | HTMLDivElement) => {
227    const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
228        theme: {
229            ...appTheme.SciChartJsTheme,
230            majorGridLineBrush: appTheme.MutedSkyBlue + "55",
231            minorGridLineBrush: appTheme.MutedSkyBlue + "22",
232        },
233    });
234
235    const xAxisCategory = new CategoryAxis(wasmContext, {
236        autoTicks: false,
237        majorDelta: 1,
238        minorDelta: 0.2,
239        axisTitle: "Category X Axis.  Hides gaps, but plots by index only",
240        axisTitleStyle: {
241            fontSize: 16,
242        },
243    });
244    if (customSettings) {
245        xAxisCategory.labelProvider = new DayOfWeekLabelProvider({ cursorLabelFormat: ENumericFormat.Date_DDMMHHMM });
246    }
247
248    const yAxisLinear = new NumericAxis(wasmContext, {
249        labelFormat: ENumericFormat.Decimal,
250        labelPrecision: 2,
251        drawMinorGridLines: false,
252        growBy: new NumberRange(0.1, 0.1),
253    });
254
255    sciChartSurface.xAxes.add(xAxisCategory);
256    sciChartSurface.yAxes.add(yAxisLinear);
257
258    const categoryDataSeries = createDataSeries(wasmContext, true);
259
260    addSeriesToChart(sciChartSurface, wasmContext, categoryDataSeries);
261
262    sciChartSurface.chartModifiers.add(
263        new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection }),
264        new ZoomExtentsModifier(),
265        new ZoomPanModifier(),
266        new RolloverModifier({ showTooltip: false, showAxisLabel: true, modifierGroup: "Group1" })
267    );
268
269    sciChartSurface.zoomExtents();
270    return { sciChartSurface, wasmContext };
271};
272

DiscontinuousDateAxis Comparison – JavaScript

Overview

This example compares three different X-axis types in SciChart.js—NumericAxis, CategoryAxis, and the new DiscontinuousDateAxis—using the same financial-style dataset. The goal is to highlight how each axis handles gaps in time, uneven sampling, and multiple data points at the same timestamp.

This comparison is mirrored in the official SciChart.js documentation, which lays out key differences between these axis types: https://www.scichart.com/documentation/js/v5/2d-charts/axis-api/axis-types/discontinuous-date-axis/#comparison-discontinuousdateaxis-vs-categoryaxis-vs-numericaxis. :contentReference[oaicite:1]{index=1}

Axis Comparison

NumericAxis (Date Values)

The NumericAxis treats date values as continuous numbers. This means:

  • All time gaps (weekends, holidays, missing data) are rendered as empty space
  • Large gaps can compress useful areas of the chart
  • Unevenly sampled data may appear misleading

While numerically accurate, this axis may not be ideal for financial or trading data.

CategoryAxis

The CategoryAxis treats points by index, completely collapsing time gaps:

  • Removes empty space between dates
  • All data points are evenly spaced regardless of time differences

However, it cannot support multiple points at the same X value or varying point densities without distortion.

DiscontinuousDateAxis ⭐

The DiscontinuousDateAxis combines the benefits of both:

  • Collapses gaps such as weekends and holidays
  • Supports multiple points at the same timestamp
  • Handles uneven or differing sample counts between series
  • Maintains relative time positioning within segments of data

In short, it collapses gaps like the CategoryAxis but still supports true time-series behavior like the NumericAxis. This improved axis type is especially useful in financial or trading visualizations where non-trading periods should be hidden. :contentReference[oaicite:2]{index=2}

Technical Implementation

In this demo, the DiscontinuousDateAxis uses base X values derived from the first series (such as an OHLC candlestick series) and a fixed dataGap to control spacing between session values. Optional custom tick formatting shows how advanced label control can be applied using a NumericLabelProvider. Cursor and rollover modifiers display accurate date-time information even when gaps are collapsed.

Features and Capabilities

Financial-Grade Time Axis: Hide weekends and non-trading periods without loss of temporal meaning.

Supports Complex Data Shapes: Multiple points per date and uneven sampling are correctly handled.

Accurate Interaction: Cursor labels, rollover modifiers, and zooming work as expected.

WebAssembly Performance: Axis and series calculations are fast, even with multiple series.

Best Practices

Use DiscontinuousDateAxis when visual space optimization and true date semantics are both required. For full details on axis comparison and configuration, see the official docs: https://www.scichart.com/documentation/js/v5/2d-charts/axis-api/axis-types/discontinuous-date-axis/#comparison-discontinuousdateaxis-vs-categoryaxis-vs-numericaxis. :contentReference[oaicite:3]{index=3}

javascript Chart Examples & Demos

See Also: Charts added in v5 (9 Demos)

NEW!
JavaScript Trading Drawing Tools | Javascript Charts | SciChart.js

JavaScript Trading Drawing Tools

Create an interactive JavaScript trading charts for technical analysis. Trading Drawing Tools Demo, which shows how to use Polylines, Extended Lines, Rays, Channels, Pitchforks, Pitchfans, Fibonnaci Retracements, Measure, Stop Loss and Take Profit chart drawing tools for Technical Analysis.

NEW!
JavaScript Freehand Drawing Tools | SciChart.js Demo

JavaScript Freehand Drawing Tools

An example of using JavaScript FreehandDrawingModifier for arbitrary drawing on trading and financial charts. Can be used for drawing trends, arrow, markers, text, etc.

NEW!
JavaScript Chart with Smith Chart | SciChart.js Demo

JavaScript Chart with Smith Chart

Interactive JavaScript Smith chart for RF impedance matching — place markers, build matching networks step by step with the component chain, and switch between impedance and admittance grids.

NEW!
High Performance SVG Cursor & Rollover | SciChart.js Demo

High Performance SVG Cursor & Rollover

Demonstrates how to use the SVG render layer in SciChart.js to maintain smooth cursor interaction on heavy charts with millions of points.

NEW!
JavaScript Force Directed Graph | Javascript Charts | SciChart.js

JavaScript Force Directed Graph

JavaScript Force Directed Graph demo by SciChart.js. Visualize network graphs with physics simulation, interactive node dragging, and hover tooltips.

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

NEW!
JavaScript Orderbook Heatmap | Javascript Charts | SciChart.js

JavaScript Orderbook Heatmap

Create a Javascript heatmap chart showing historical orderbook levels using the high performance SciChart.js chart library. Get free demo now.

NEW!
High Precision Date Axis | Javascript Charts | SciChart.js Demo

High Precision Date Axis

Demonstrates 64-bit precision Date Axis in SciChart.js handling Nanoseconds to Billions of Years

NEW!
JavaScript Chart with BaseValue Axes | SciChart.js Demo

JavaScript Chart with BaseValue Axes

Demonstrates BaseValue Axes on a JavaScript Chart using SciChart.js to create non-linear and custom-scaled axes such as log-like scales

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