DevExtreme v24.1 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

React Charts - Scale Breaks

Scale breaks (wavy stripes you see on the chart) cut out ranges from the value axis. This technique may enhance chart readability if values differ greatly. As you can see in this demo, you can easily compare smaller values if scale breaks are enabled. If you disable scale breaks, the smaller values are indistinguishable.

The Chart component can generate scale breaks on the valueAxis. The Chart detects large gaps between side-by-side points, cuts them out, and displays scale breaks instead. Scale breaks are available only for 'continuous' or 'logarithmic' axis types.

Backend API
import React, { useCallback, useState } from 'react'; import Chart, { Legend, Series, Tooltip, ValueAxis, BreakStyle, } from 'devextreme-react/chart'; import SelectBox, { SelectBoxTypes } from 'devextreme-react/select-box'; import CheckBox, { CheckBoxTypes } from 'devextreme-react/check-box'; import { dataSource, lineStyleLabel, maxCountLabel } from './data.ts'; const lineStyles: ('straight' | 'waved')[] = ['waved', 'straight']; const breaksCount = [1, 2, 3, 4]; function App() { const [autoBreaksEnabledValue, setAutoBreaksEnabledValue] = useState(true); const [breaksCountValue, setBreaksCountValue] = useState(3); const [lineStyleValue, setLineStyleValue] = useState(lineStyles[0]); const changeBreaksCount = useCallback((e: SelectBoxTypes.ValueChangedEvent) => { setBreaksCountValue(e.value); }, [setBreaksCountValue]); const changeStyle = useCallback((e: SelectBoxTypes.ValueChangedEvent) => { setLineStyleValue(e.value); }, [setLineStyleValue]); const changeBreaksEnabledState = useCallback((e: CheckBoxTypes.ValueChangedEvent) => { setAutoBreaksEnabledValue(e.value); }, [setAutoBreaksEnabledValue]); return ( <div> <Chart id="chart" title={'Relative Masses of the Heaviest\n Solar System Objects'} dataSource={dataSource}> <Series valueField="mass" argumentField="name" type="bar" /> <ValueAxis visible={true} autoBreaksEnabled={autoBreaksEnabledValue} maxAutoBreakCount={breaksCountValue}> <BreakStyle line={lineStyleValue} /> </ValueAxis> <Legend visible={false} /> <Tooltip enabled={true} /> </Chart> <div className="options"> <div className="caption">Options</div> <div className="options-container"> <div className="option"> <CheckBox className="checkbox" text="Enable Breaks" onValueChanged={changeBreaksEnabledState} value={autoBreaksEnabledValue} /> </div> <div className="option"> <span>Max Count </span> <SelectBox items={breaksCount} inputAttr={maxCountLabel} value={breaksCountValue} onValueChanged={changeBreaksCount} width={80} /> </div> <div className="option"> <span>Style </span> <SelectBox items={lineStyles} inputAttr={lineStyleLabel} value={lineStyleValue} onValueChanged={changeStyle} width={120} /> </div> </div> </div> </div> ); } export default App;
import React, { useCallback, useState } from 'react'; import Chart, { Legend, Series, Tooltip, ValueAxis, BreakStyle, } from 'devextreme-react/chart'; import SelectBox from 'devextreme-react/select-box'; import CheckBox from 'devextreme-react/check-box'; import { dataSource, lineStyleLabel, maxCountLabel } from './data.js'; const lineStyles = ['waved', 'straight']; const breaksCount = [1, 2, 3, 4]; function App() { const [autoBreaksEnabledValue, setAutoBreaksEnabledValue] = useState(true); const [breaksCountValue, setBreaksCountValue] = useState(3); const [lineStyleValue, setLineStyleValue] = useState(lineStyles[0]); const changeBreaksCount = useCallback( (e) => { setBreaksCountValue(e.value); }, [setBreaksCountValue], ); const changeStyle = useCallback( (e) => { setLineStyleValue(e.value); }, [setLineStyleValue], ); const changeBreaksEnabledState = useCallback( (e) => { setAutoBreaksEnabledValue(e.value); }, [setAutoBreaksEnabledValue], ); return ( <div> <Chart id="chart" title={'Relative Masses of the Heaviest\n Solar System Objects'} dataSource={dataSource} > <Series valueField="mass" argumentField="name" type="bar" /> <ValueAxis visible={true} autoBreaksEnabled={autoBreaksEnabledValue} maxAutoBreakCount={breaksCountValue} > <BreakStyle line={lineStyleValue} /> </ValueAxis> <Legend visible={false} /> <Tooltip enabled={true} /> </Chart> <div className="options"> <div className="caption">Options</div> <div className="options-container"> <div className="option"> <CheckBox className="checkbox" text="Enable Breaks" onValueChanged={changeBreaksEnabledState} value={autoBreaksEnabledValue} /> </div> <div className="option"> <span>Max Count </span> <SelectBox items={breaksCount} inputAttr={maxCountLabel} value={breaksCountValue} onValueChanged={changeBreaksCount} width={80} /> </div> <div className="option"> <span>Style </span> <SelectBox items={lineStyles} inputAttr={lineStyleLabel} value={lineStyleValue} onValueChanged={changeStyle} width={120} /> </div> </div> </div> </div> ); } export default App;
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.tsx'; ReactDOM.render( <App />, document.getElementById('app'), );
export const dataSource = [{ name: 'Jupiter', mass: 318, }, { name: 'Saturn', mass: 95, }, { name: 'Uranus', mass: 14.6, }, { name: 'Neptune', mass: 17.2, }, { name: 'Earth', mass: 1, }, { name: 'Venus', mass: 0.82, }, { name: 'Mars', mass: 0.11, }, { name: 'Mercury', mass: 0.06, }]; export const maxCountLabel = { 'aria-label': 'Max Count' }; export const lineStyleLabel = { 'aria-label': 'Line Style' };
window.exports = window.exports || {}; window.config = { transpiler: 'ts', typescriptOptions: { module: 'system', emitDecoratorMetadata: true, experimentalDecorators: true, jsx: 'react', }, meta: { 'react': { 'esModule': true, }, 'typescript': { 'exports': 'ts', }, 'devextreme/time_zone_utils.js': { 'esModule': true, }, 'devextreme/localization.js': { 'esModule': true, }, 'devextreme/viz/palette.js': { 'esModule': true, }, }, paths: { 'npm:': 'https://unpkg.com/', }, defaultExtension: 'js', map: { 'ts': 'npm:plugin-typescript@4.2.4/lib/plugin.js', 'typescript': 'npm:typescript@4.2.4/lib/typescript.js', 'react': 'npm:react@17.0.2/umd/react.development.js', 'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js', 'prop-types': 'npm:prop-types@15.8.1/prop-types.js', 'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js', 'luxon': 'npm:luxon@1.28.1/build/global/luxon.min.js', 'es6-object-assign': 'npm:es6-object-assign@1.1.0', 'devextreme': 'npm:devextreme@24.1.7/cjs', 'devextreme-react': 'npm:devextreme-react@24.1.7/cjs', 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', 'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.13/dist/dx-diagram.js', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.56/dist/dx-gantt.js', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.13', 'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js', 'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js', 'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js', 'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js', 'inferno-hydrate': 'npm:inferno-hydrate@7.4.11/dist/inferno-hydrate.min.js', 'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js', 'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js', 'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js', 'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3', // SystemJS plugins 'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js', 'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js', // Prettier 'prettier/standalone': 'npm:prettier@2.8.8/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js', }, packages: { 'devextreme': { defaultExtension: 'js', }, 'devextreme-react': { main: 'index.js', }, 'devextreme/events/utils': { main: 'index', }, 'devextreme/localization/messages': { format: 'json', defaultExtension: 'json', }, 'devextreme/events': { main: 'index', }, 'es6-object-assign': { main: './index.js', defaultExtension: 'js', }, }, packageConfigPaths: [ 'npm:@devextreme/*/package.json', 'npm:@devextreme/runtime@3.0.13/inferno/package.json', ], babelOptions: { sourceMaps: false, stage0: true, react: true, }, }; System.config(window.config);
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js'; ReactDOM.render(<App />, document.getElementById('app'));
export const dataSource = [ { name: 'Jupiter', mass: 318, }, { name: 'Saturn', mass: 95, }, { name: 'Uranus', mass: 14.6, }, { name: 'Neptune', mass: 17.2, }, { name: 'Earth', mass: 1, }, { name: 'Venus', mass: 0.82, }, { name: 'Mars', mass: 0.11, }, { name: 'Mercury', mass: 0.06, }, ]; export const maxCountLabel = { 'aria-label': 'Max Count' }; export const lineStyleLabel = { 'aria-label': 'Line Style' };
<!DOCTYPE html> <html lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/24.1.7/css/dx.light.css" /> <link rel="stylesheet" type="text/css" href="styles.css" /> <script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import("./index.tsx"); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"></div> </div> </body> </html>
#chart { height: 440px; } .options { padding: 20px; background-color: rgba(191, 191, 191, 0.15); margin-top: 20px; } .caption { font-size: 18px; font-weight: 500; } .option { display: inline-block; margin-right: 70px; margin-top: 5px; } .option > span { margin: 0 10px 0 0; } .checkbox { margin-top: -4px; } .option > .dx-widget { display: inline-block; vertical-align: middle; } .options-container { display: flex; align-items: center; }

To enable auto-calculated scale breaks, set the autoBreaksEnabled property to true. Use the maxAutoBreakCount property to limit the number of automatically created scale breaks. To configure scale break appearance, use the breakStyle object. You can test all these options in the demo.

You can also create custom breaks, including breaks on the argumentAxis. Use the breaks array to declare a scale break collection. Each object in this array must specify the startValue and endValue fields that limit a single scale break. Note that breaks smaller than two ticks might not appear on the chart.