DevExtreme v24.2 is now available.

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

Your search did not match any results.

React Charts - Zooming and Panning API

This example demonstrates how you can connect the Chart and RangeSelector components in order to zoom into the appropriate data range within the Chart. Move the sliders along the RangeSelector, and you will note that the value axis of the Chart is adjusted automatically.

Backend API
import React, { useCallback, useState } from 'react'; import Chart, { Series, Legend, CommonSeriesSettings, Point, ArgumentAxis, } from 'devextreme-react/chart'; import RangeSelector, { Size, Chart as ChartOptions, Margin, Scale, Behavior, RangeSelectorTypes, } from 'devextreme-react/range-selector'; import { VisualRange } from 'devextreme-react/common/charts'; import { zoomingData } from './data.ts'; function App() { const [visualRange, setVisualRange] = useState<VisualRange>({ startValue: 10, endValue: 880 }); const updateVisualRange = useCallback((e: RangeSelectorTypes.ValueChangedEvent) => { setVisualRange(e.value); }, [setVisualRange]); return ( <React.Fragment> <Chart id="zoomedChart" palette="Harmony Light" dataSource={zoomingData} > <Series argumentField="arg" valueField="y1" /> <Series argumentField="arg" valueField="y2" /> <Series argumentField="arg" valueField="y3" /> <ArgumentAxis visualRange={visualRange} /> <Legend visible={false} /> <CommonSeriesSettings> <Point size={7} /> </CommonSeriesSettings> </Chart> <RangeSelector dataSource={zoomingData} onValueChanged={updateVisualRange} > <Behavior valueChangeMode="onHandleMove" /> <Size height={120} /> <Margin left={10} /> <Scale minorTickCount={1} startValue={10} endValue={880} /> <ChartOptions palette="Harmony Light"> <Legend visible={false} /> <Series argumentField="arg" valueField="y1" /> <Series argumentField="arg" valueField="y2" /> <Series argumentField="arg" valueField="y3" /> </ChartOptions> </RangeSelector> </React.Fragment> ); } export default App;
import React, { useCallback, useState } from 'react'; import Chart, { Series, Legend, CommonSeriesSettings, Point, ArgumentAxis, } from 'devextreme-react/chart'; import RangeSelector, { Size, Chart as ChartOptions, Margin, Scale, Behavior, } from 'devextreme-react/range-selector'; import { zoomingData } from './data.js'; function App() { const [visualRange, setVisualRange] = useState({ startValue: 10, endValue: 880 }); const updateVisualRange = useCallback( (e) => { setVisualRange(e.value); }, [setVisualRange], ); return ( <React.Fragment> <Chart id="zoomedChart" palette="Harmony Light" dataSource={zoomingData} > <Series argumentField="arg" valueField="y1" /> <Series argumentField="arg" valueField="y2" /> <Series argumentField="arg" valueField="y3" /> <ArgumentAxis visualRange={visualRange} /> <Legend visible={false} /> <CommonSeriesSettings> <Point size={7} /> </CommonSeriesSettings> </Chart> <RangeSelector dataSource={zoomingData} onValueChanged={updateVisualRange} > <Behavior valueChangeMode="onHandleMove" /> <Size height={120} /> <Margin left={10} /> <Scale minorTickCount={1} startValue={10} endValue={880} /> <ChartOptions palette="Harmony Light"> <Legend visible={false} /> <Series argumentField="arg" valueField="y1" /> <Series argumentField="arg" valueField="y2" /> <Series argumentField="arg" valueField="y3" /> </ChartOptions> </RangeSelector> </React.Fragment> ); } export default App;
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.tsx'; ReactDOM.render( <App />, document.getElementById('app'), );
const zoomingData = [ { arg: 10, y1: -12, y2: 10, y3: 32, }, { arg: 20, y1: -32, y2: 30, y3: 12, }, { arg: 40, y1: -20, y2: 20, y3: 30, }, { arg: 50, y1: -39, y2: 50, y3: 19, }, { arg: 60, y1: -10, y2: 10, y3: 15, }, { arg: 75, y1: 10, y2: 10, y3: 15, }, { arg: 80, y1: 30, y2: 50, y3: 13, }, { arg: 90, y1: 40, y2: 50, y3: 14, }, { arg: 100, y1: 50, y2: 90, y3: 90, }, { arg: 105, y1: 40, y2: 175, y3: 120, }, { arg: 110, y1: -12, y2: 10, y3: 32, }, { arg: 120, y1: -32, y2: 30, y3: 12, }, { arg: 130, y1: -20, y2: 20, y3: 30, }, { arg: 140, y1: -12, y2: 10, y3: 32, }, { arg: 150, y1: -32, y2: 30, y3: 12, }, { arg: 160, y1: -20, y2: 20, y3: 30, }, { arg: 170, y1: -39, y2: 50, y3: 19, }, { arg: 180, y1: -10, y2: 10, y3: 15, }, { arg: 185, y1: 10, y2: 10, y3: 15, }, { arg: 190, y1: 30, y2: 100, y3: 13, }, { arg: 200, y1: 40, y2: 110, y3: 14, }, { arg: 210, y1: 50, y2: 90, y3: 90, }, { arg: 220, y1: 40, y2: 95, y3: 120, }, { arg: 230, y1: -12, y2: 10, y3: 32, }, { arg: 240, y1: -32, y2: 30, y3: 12, }, { arg: 255, y1: -20, y2: 20, y3: 30, }, { arg: 270, y1: -12, y2: 10, y3: 32, }, { arg: 280, y1: -32, y2: 30, y3: 12, }, { arg: 290, y1: -20, y2: 20, y3: 30, }, { arg: 295, y1: -39, y2: 50, y3: 19, }, { arg: 300, y1: -10, y2: 10, y3: 15, }, { arg: 310, y1: 10, y2: 10, y3: 15, }, { arg: 320, y1: 30, y2: 100, y3: 13, }, { arg: 330, y1: 40, y2: 110, y3: 14, }, { arg: 340, y1: 50, y2: 90, y3: 90, }, { arg: 350, y1: 40, y2: 95, y3: 120, }, { arg: 360, y1: -12, y2: 10, y3: 32, }, { arg: 367, y1: -32, y2: 30, y3: 12, }, { arg: 370, y1: -20, y2: 20, y3: 30, }, { arg: 380, y1: -12, y2: 10, y3: 32, }, { arg: 390, y1: -32, y2: 30, y3: 12, }, { arg: 400, y1: -20, y2: 20, y3: 30, }, { arg: 410, y1: -39, y2: 50, y3: 19, }, { arg: 420, y1: -10, y2: 10, y3: 15, }, { arg: 430, y1: 10, y2: 10, y3: 15, }, { arg: 440, y1: 30, y2: 100, y3: 13, }, { arg: 450, y1: 40, y2: 110, y3: 14, }, { arg: 460, y1: 50, y2: 90, y3: 90, }, { arg: 470, y1: 40, y2: 95, y3: 120, }, { arg: 480, y1: -12, y2: 10, y3: 32, }, { arg: 490, y1: -32, y2: 30, y3: 12, }, { arg: 500, y1: -20, y2: 20, y3: 30, }, { arg: 510, y1: -12, y2: 10, y3: 32, }, { arg: 520, y1: -32, y2: 30, y3: 12, }, { arg: 530, y1: -20, y2: 20, y3: 30, }, { arg: 540, y1: -39, y2: 50, y3: 19, }, { arg: 550, y1: -10, y2: 10, y3: 15, }, { arg: 555, y1: 10, y2: 10, y3: 15, }, { arg: 560, y1: 30, y2: 100, y3: 13, }, { arg: 570, y1: 40, y2: 110, y3: 14, }, { arg: 580, y1: 50, y2: 90, y3: 90, }, { arg: 590, y1: 40, y2: 95, y3: 12, }, { arg: 600, y1: -12, y2: 10, y3: 32, }, { arg: 610, y1: -32, y2: 30, y3: 12, }, { arg: 620, y1: -20, y2: 20, y3: 30, }, { arg: 630, y1: -12, y2: 10, y3: 32, }, { arg: 640, y1: -32, y2: 30, y3: 12, }, { arg: 650, y1: -20, y2: 20, y3: 30, }, { arg: 660, y1: -39, y2: 50, y3: 19, }, { arg: 670, y1: -10, y2: 10, y3: 15, }, { arg: 680, y1: 10, y2: 10, y3: 15, }, { arg: 690, y1: 30, y2: 100, y3: 13, }, { arg: 700, y1: 40, y2: 110, y3: 14, }, { arg: 710, y1: 50, y2: 90, y3: 90, }, { arg: 720, y1: 40, y2: 95, y3: 120, }, { arg: 730, y1: 20, y2: 190, y3: 130, }, { arg: 740, y1: -32, y2: 30, y3: 12, }, { arg: 750, y1: -20, y2: 20, y3: 30, }, { arg: 760, y1: -12, y2: 10, y3: 32, }, { arg: 770, y1: -32, y2: 30, y3: 12, }, { arg: 780, y1: -20, y2: 20, y3: 30, }, { arg: 790, y1: -39, y2: 50, y3: 19, }, { arg: 800, y1: -10, y2: 10, y3: 15, }, { arg: 810, y1: 10, y2: 10, y3: 15, }, { arg: 820, y1: 30, y2: 100, y3: 13, }, { arg: 830, y1: 40, y2: 110, y3: 14, }, { arg: 840, y1: 50, y2: 90, y3: 90, }, { arg: 850, y1: 40, y2: 95, y3: 120, }, { arg: 860, y1: -12, y2: 10, y3: 32, }, { arg: 870, y1: -32, y2: 30, y3: 12, }, { arg: 880, y1: -20, y2: 20, y3: 30, }, ]; export { zoomingData, };
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, }, 'openai': { 'esModule': true, }, }, paths: { 'npm:': 'https://unpkg.com/', 'bundles:': '../../../../bundles/', 'externals:': '../../../../bundles/externals/', }, defaultExtension: 'js', map: { 'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js', 'typescript': 'npm:typescript@4.2.4/lib/typescript.js', 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.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/prop-types.js', 'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js', 'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js', 'es6-object-assign': 'npm:es6-object-assign', 'devextreme': 'npm:devextreme@link:../../packages/devextreme/artifacts/npm/devextreme/cjs', 'devextreme-react': 'npm:devextreme-react@link:../../packages/devextreme-react/npm/cjs', 'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.54/dist/dx-gantt.js', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12', '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/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.12/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'));
const zoomingData = [ { arg: 10, y1: -12, y2: 10, y3: 32, }, { arg: 20, y1: -32, y2: 30, y3: 12, }, { arg: 40, y1: -20, y2: 20, y3: 30, }, { arg: 50, y1: -39, y2: 50, y3: 19, }, { arg: 60, y1: -10, y2: 10, y3: 15, }, { arg: 75, y1: 10, y2: 10, y3: 15, }, { arg: 80, y1: 30, y2: 50, y3: 13, }, { arg: 90, y1: 40, y2: 50, y3: 14, }, { arg: 100, y1: 50, y2: 90, y3: 90, }, { arg: 105, y1: 40, y2: 175, y3: 120, }, { arg: 110, y1: -12, y2: 10, y3: 32, }, { arg: 120, y1: -32, y2: 30, y3: 12, }, { arg: 130, y1: -20, y2: 20, y3: 30, }, { arg: 140, y1: -12, y2: 10, y3: 32, }, { arg: 150, y1: -32, y2: 30, y3: 12, }, { arg: 160, y1: -20, y2: 20, y3: 30, }, { arg: 170, y1: -39, y2: 50, y3: 19, }, { arg: 180, y1: -10, y2: 10, y3: 15, }, { arg: 185, y1: 10, y2: 10, y3: 15, }, { arg: 190, y1: 30, y2: 100, y3: 13, }, { arg: 200, y1: 40, y2: 110, y3: 14, }, { arg: 210, y1: 50, y2: 90, y3: 90, }, { arg: 220, y1: 40, y2: 95, y3: 120, }, { arg: 230, y1: -12, y2: 10, y3: 32, }, { arg: 240, y1: -32, y2: 30, y3: 12, }, { arg: 255, y1: -20, y2: 20, y3: 30, }, { arg: 270, y1: -12, y2: 10, y3: 32, }, { arg: 280, y1: -32, y2: 30, y3: 12, }, { arg: 290, y1: -20, y2: 20, y3: 30, }, { arg: 295, y1: -39, y2: 50, y3: 19, }, { arg: 300, y1: -10, y2: 10, y3: 15, }, { arg: 310, y1: 10, y2: 10, y3: 15, }, { arg: 320, y1: 30, y2: 100, y3: 13, }, { arg: 330, y1: 40, y2: 110, y3: 14, }, { arg: 340, y1: 50, y2: 90, y3: 90, }, { arg: 350, y1: 40, y2: 95, y3: 120, }, { arg: 360, y1: -12, y2: 10, y3: 32, }, { arg: 367, y1: -32, y2: 30, y3: 12, }, { arg: 370, y1: -20, y2: 20, y3: 30, }, { arg: 380, y1: -12, y2: 10, y3: 32, }, { arg: 390, y1: -32, y2: 30, y3: 12, }, { arg: 400, y1: -20, y2: 20, y3: 30, }, { arg: 410, y1: -39, y2: 50, y3: 19, }, { arg: 420, y1: -10, y2: 10, y3: 15, }, { arg: 430, y1: 10, y2: 10, y3: 15, }, { arg: 440, y1: 30, y2: 100, y3: 13, }, { arg: 450, y1: 40, y2: 110, y3: 14, }, { arg: 460, y1: 50, y2: 90, y3: 90, }, { arg: 470, y1: 40, y2: 95, y3: 120, }, { arg: 480, y1: -12, y2: 10, y3: 32, }, { arg: 490, y1: -32, y2: 30, y3: 12, }, { arg: 500, y1: -20, y2: 20, y3: 30, }, { arg: 510, y1: -12, y2: 10, y3: 32, }, { arg: 520, y1: -32, y2: 30, y3: 12, }, { arg: 530, y1: -20, y2: 20, y3: 30, }, { arg: 540, y1: -39, y2: 50, y3: 19, }, { arg: 550, y1: -10, y2: 10, y3: 15, }, { arg: 555, y1: 10, y2: 10, y3: 15, }, { arg: 560, y1: 30, y2: 100, y3: 13, }, { arg: 570, y1: 40, y2: 110, y3: 14, }, { arg: 580, y1: 50, y2: 90, y3: 90, }, { arg: 590, y1: 40, y2: 95, y3: 12, }, { arg: 600, y1: -12, y2: 10, y3: 32, }, { arg: 610, y1: -32, y2: 30, y3: 12, }, { arg: 620, y1: -20, y2: 20, y3: 30, }, { arg: 630, y1: -12, y2: 10, y3: 32, }, { arg: 640, y1: -32, y2: 30, y3: 12, }, { arg: 650, y1: -20, y2: 20, y3: 30, }, { arg: 660, y1: -39, y2: 50, y3: 19, }, { arg: 670, y1: -10, y2: 10, y3: 15, }, { arg: 680, y1: 10, y2: 10, y3: 15, }, { arg: 690, y1: 30, y2: 100, y3: 13, }, { arg: 700, y1: 40, y2: 110, y3: 14, }, { arg: 710, y1: 50, y2: 90, y3: 90, }, { arg: 720, y1: 40, y2: 95, y3: 120, }, { arg: 730, y1: 20, y2: 190, y3: 130, }, { arg: 740, y1: -32, y2: 30, y3: 12, }, { arg: 750, y1: -20, y2: 20, y3: 30, }, { arg: 760, y1: -12, y2: 10, y3: 32, }, { arg: 770, y1: -32, y2: 30, y3: 12, }, { arg: 780, y1: -20, y2: 20, y3: 30, }, { arg: 790, y1: -39, y2: 50, y3: 19, }, { arg: 800, y1: -10, y2: 10, y3: 15, }, { arg: 810, y1: 10, y2: 10, y3: 15, }, { arg: 820, y1: 30, y2: 100, y3: 13, }, { arg: 830, y1: 40, y2: 110, y3: 14, }, { arg: 840, y1: 50, y2: 90, y3: 90, }, { arg: 850, y1: 40, y2: 95, y3: 120, }, { arg: 860, y1: -12, y2: 10, y3: 32, }, { arg: 870, y1: -32, y2: 30, y3: 12, }, { arg: 880, y1: -20, y2: 20, y3: 30, }, ]; export { zoomingData };
<!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.2.3/css/dx.light.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> <link rel="stylesheet" type="text/css" href="styles.css" /> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"></div> </div> </body> </html>