DiscontinuousDateAxis Comparison with React

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 – React

Overview

This example demonstrates how DiscontinuousDateAxis compares to NumericAxis and CategoryAxis in a React application using SciChart.js. Identical datasets are displayed using each axis type to show how gaps and uneven sampling are handled.

You can review the official axis comparison guide here: https://www.scichart.com/documentation/js/v5/2d-charts/axis-api/axis-types/discontinuous-date-axis/#comparison-discontinuousdateaxis-vs-categoryaxis-vs-numericaxis. :contentReference[oaicite:4]{index=4}

Axis Comparison

NumericAxis

NumericAxis plots date values continuously, meaning weekends and missing periods appear as empty space. This often compresses actual data segments and can distort visual insights.

CategoryAxis

CategoryAxis collapses all gaps by plotting points by index. While this removes empty space, it does not preserve true date spacing and cannot support multiple points at the same X value.

DiscontinuousDateAxis

DiscontinuousDateAxis collapses gaps like CategoryAxis, but also:

  • Allows multiple points at the same date
  • Preserves relative time positioning within each segment
  • Handles series with different numbers of points

This makes it ideal for financial and irregular time-series data. :contentReference[oaicite:5]{index=5}

Technical Implementation

In React, each chart instance uses the same data and renderable series setup, but a different axis type. The DiscontinuousDateAxis uses baseValues from the first data series and a fixed dataGap to define the coordinate system. Optional tick and label customizations demonstrate how to create intuitive date labels using custom providers.

For interactive exploration, rollover modifiers display correct date/time labels and zoom/pan modifiers respect the collapsed gaps while maintaining accurate value interpretation.

Features and Best Practices

React-Friendly Integration: Chart creation logic is isolated from component rendering.

Accurate Guides and Interactions: Cursor and rollover labels show accurate date values even when gaps are collapsed.

Configuration Flexibility: Major and minor ticks can be customized manually.

High Performance: Driven by SciChart’s WebAssembly engine.

Refer to the official axis comparison docs for more details: https://www.scichart.com/documentation/js/v5/2d-charts/axis-api/axis-types/discontinuous-date-axis/#comparison-discontinuousdateaxis-vs-categoryaxis-vs-numericaxis. :contentReference[oaicite:6]{index=6}

react Chart Examples & Demos

See Also: Chart Axis APIs (11 Demos)

React Chart with Multiple X Axes | React Charts | SciChart.js

React Chart with Multiple X Axes

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

React Chart with Secondary Y Axes | SciChart.js Demo

React Chart with Secondary Y Axes

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

React Vertical Charts | React Charts | SciChart.js Demo

React Vertical Charts

Demonstrates alignment of Axis to create a vertical chart with SciChart.js - JavaScript Charts.

React Chart with Central Axes | React Charts | SciChart.js

React Chart with Central Axes

Demonstrates Central Axes on a React Chart using SciChart.js. SciChart supports unlimited left, right, top, bottom X, Y axis with configurable layout

React Chart with Static X Axis | React Charts | SciChart.js

React Chart with Static X Axis

Demonstrates isStaticAxis on a React Chart using SciChart.js.

React Chart with Vertically Stacked Axes | SciChart.js

React Chart with Vertically Stacked Axes

Demonstrates Vertically Stacked Axes on a React Chart using SciChart.js, allowing data to overlap

React Chart with Logarithmic Axis Example | SciChart.js

React Chart with Logarithmic Axis Example

Demonstrates Logarithmic Axis on a React Chart using SciChart.js. SciChart supports logarithmic axis with scientific or engineering notation and positive and negative values

NEW!
React Chart with BaseValue Axes | React Charts | SciChart.js

React Chart with BaseValue Axes

Demonstrates BaseValue Axes on a React Chart using SciChart.js to create non-linear and custom-scaled axes

Draw React Chart Behind Axis | React Charts | SciChart.js

Draw React Chart Behind Axis

Demonstrates the option of the transparent Axes customization on a React Chart using SciChart.js.

Axis Types | React Charts | SciChart.js Demo

Axis Types

Demonstrates how to use arbitrary text for axis labels, rather than formatted data values, using the new TextLabelProvider

React Chart Axis Layout Options | React Charts | SciChart.js

React Chart Axis Layout Options

Demonstrates outer, inner, central and stacked axes, and use of axis alignment to create vertical charts

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