DevExtreme v23.1 is now available.

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

Your search did not match any results.
Bar 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.

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.

Backend API
Copy to CodeSandBox
import React 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]; class App extends React.Component { constructor(props) { super(props); this.state = { autoBreaksEnabledValue: true, breaksCountValue: 3, lineStyleValue: lineStyles[0], }; this.changeBreaksCount = (e) => { this.setState({ breaksCountValue: e.value, }); }; this.changeStyle = (e) => { this.setState({ lineStyleValue: e.value, }); }; this.changeBreaksEnabledState = (e) => { this.setState({ autoBreaksEnabledValue: e.value, }); }; } render() { 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={this.state.autoBreaksEnabledValue} maxAutoBreakCount={this.state.breaksCountValue}> <BreakStyle line={this.state.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={this.changeBreaksEnabledState} value={this.state.autoBreaksEnabledValue}> </CheckBox> </div> <div className="option"> <span>Max Count </span> <SelectBox items={breaksCount} inputAttr={maxCountLabel} value={this.state.breaksCountValue} onValueChanged={this.changeBreaksCount} width={80}> </SelectBox> </div> <div className="option"> <span>Style </span> <SelectBox items={lineStyles} inputAttr={lineStyleLabel} value={this.state.lineStyleValue} onValueChanged={this.changeStyle} width={120}> </SelectBox> </div> </div> </div> </div> ); } } export default App;
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js'; ReactDOM.render( <App />, document.getElementById('app'), );
<!DOCTYPE html> <html> <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=1.0" /> <link rel="stylesheet" type="text/css" href="" /> <link rel="stylesheet" type="text/css" href="styles.css" /> <script src=""></script> <script src=""></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import("./index.js"); </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; }
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.config = { transpiler: 'plugin-babel', meta: { 'devextreme/localization.js': { 'esModule': true, }, }, paths: { 'npm:': '', }, defaultExtension: 'js', map: { '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@23.1.5/cjs', 'devextreme-react': 'npm:devextreme-react@23.1.5', 'jszip': 'npm:jszip@3.7.1/dist/jszip.min.js', 'devextreme-quill': 'npm:devextreme-quill@1.6.2/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.1/dist/dx-diagram.js', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.48/dist/dx-gantt.js', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.11', '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', // 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.4/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.4/parser-html.js', }, packages: { 'devextreme': { defaultExtension: 'js', }, 'devextreme-react': { main: 'index.js', }, 'devextreme/events/utils': { main: 'index', }, 'devextreme/events': { main: 'index', }, 'es6-object-assign': { main: './index.js', defaultExtension: 'js', }, }, packageConfigPaths: [ 'npm:@devextreme/*/package.json', 'npm:@devextreme/runtime@3.0.11/inferno/package.json', ], babelOptions: { sourceMaps: false, stage0: true, react: true, }, }; System.config(window.config);