DevExtreme v23.2 is now available.

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

Your search did not match any results.

Spline

Spline charts, like line charts, allow you to visualize data and display them as lines with points placed over specified intervals. However, spline charts smooth out individual lines that connect data points.

In this example, you can use the drop-down menu under the chart to switch between the Spline, Stacked Spline, and Full-Stacked Spline chart types. A Stacked Spline chart visualizes multiple data series and allows you to compare the manner in which each series contributes to the total aggregate value for specific arguments. A Full-Stacked Spline chart helps compare the percentage value of multiple line series for each argument.

Configure Spline Charts

The functionality of Spline charts is very similar to that of line charts. You can use instructions from the Line demo description to configure Spline charts. To display a Spline, Stacked Spline, or Full-Stacked Spline series, set the type property to one of these types.

Backend API
import React, { useCallback, useState } from 'react'; import SelectBox, { SelectBoxTypes } from 'devextreme-react/select-box'; import { Chart, Series, ArgumentAxis, CommonSeriesSettings, ICommonSeriesSettingsProps, CommonAxisSettings, Grid, Export, Legend, Margin, Tooltip, Label, Format, } from 'devextreme-react/chart'; import { architectureSources, sharingStatisticsInfo, seriesTypeLabel } from './data.ts'; const types: (ICommonSeriesSettingsProps['type'])[] = ['spline', 'stackedspline', 'fullstackedspline']; function App() { const [type, setType] = useState(types[0]); const handleChange = useCallback((e: SelectBoxTypes.ValueChangedEvent) => { setType(e.value); }, [setType]); return ( <React.Fragment> <Chart palette="Violet" dataSource={sharingStatisticsInfo} title="Architecture Share Over Time (Count)" > <CommonSeriesSettings argumentField="year" type={type} /> <CommonAxisSettings> <Grid visible={true} /> </CommonAxisSettings> { architectureSources.map((item) => <Series key={item.value} valueField={item.value} name={item.name} />) } <Margin bottom={20} /> <ArgumentAxis allowDecimals={false} axisDivisionFactor={60} > <Label> <Format type="decimal" /> </Label> </ArgumentAxis> <Legend verticalAlignment="top" horizontalAlignment="right" /> <Export enabled={true} /> <Tooltip enabled={true} /> </Chart> <div className="options"> <div className="caption">Options</div> <div className="option"> <span>Series Type </span> <SelectBox dataSource={types} inputAttr={seriesTypeLabel} value={type} onValueChanged={handleChange} /> </div> </div> </React.Fragment> ); } export default App;
import React, { useCallback, useState } from 'react'; import SelectBox from 'devextreme-react/select-box'; import { Chart, Series, ArgumentAxis, CommonSeriesSettings, CommonAxisSettings, Grid, Export, Legend, Margin, Tooltip, Label, Format, } from 'devextreme-react/chart'; import { architectureSources, sharingStatisticsInfo, seriesTypeLabel } from './data.js'; const types = ['spline', 'stackedspline', 'fullstackedspline']; function App() { const [type, setType] = useState(types[0]); const handleChange = useCallback( (e) => { setType(e.value); }, [setType], ); return ( <React.Fragment> <Chart palette="Violet" dataSource={sharingStatisticsInfo} title="Architecture Share Over Time (Count)" > <CommonSeriesSettings argumentField="year" type={type} /> <CommonAxisSettings> <Grid visible={true} /> </CommonAxisSettings> {architectureSources.map((item) => ( <Series key={item.value} valueField={item.value} name={item.name} /> ))} <Margin bottom={20} /> <ArgumentAxis allowDecimals={false} axisDivisionFactor={60} > <Label> <Format type="decimal" /> </Label> </ArgumentAxis> <Legend verticalAlignment="top" horizontalAlignment="right" /> <Export enabled={true} /> <Tooltip enabled={true} /> </Chart> <div className="options"> <div className="caption">Options</div> <div className="option"> <span>Series Type </span> <SelectBox dataSource={types} inputAttr={seriesTypeLabel} value={type} onValueChanged={handleChange} /> </div> </div> </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'), );
export const architectureSources = [ { value: 'smp', name: 'SMP' }, { value: 'mmp', name: 'MMP' }, { value: 'cnstl', name: 'Cnstl' }, { value: 'cluster', name: 'Cluster' }, ]; export const sharingStatisticsInfo = [{ year: 1997, smp: 263, mmp: 208, cnstl: 9, cluster: 1, }, { year: 1999, smp: 169, mmp: 270, cnstl: 61, cluster: 7, }, { year: 2001, smp: 57, mmp: 261, cnstl: 157, cluster: 45, }, { year: 2003, smp: 0, mmp: 154, cnstl: 121, cluster: 211, }, { year: 2005, smp: 0, mmp: 97, cnstl: 39, cluster: 382, }, { year: 2007, smp: 0, mmp: 83, cnstl: 3, cluster: 437, }]; export const seriesTypeLabel = { 'aria-label': 'Series Type' };
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@23.2.5/cjs', 'devextreme-react': 'npm:devextreme-react@23.2.5/cjs', 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', 'devextreme-quill': 'npm:devextreme-quill@1.6.4/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.51/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@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.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/localization/messages': { format: 'json', defaultExtension: '', }, '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'));
export const architectureSources = [ { value: 'smp', name: 'SMP' }, { value: 'mmp', name: 'MMP' }, { value: 'cnstl', name: 'Cnstl' }, { value: 'cluster', name: 'Cluster' }, ]; export const sharingStatisticsInfo = [ { year: 1997, smp: 263, mmp: 208, cnstl: 9, cluster: 1, }, { year: 1999, smp: 169, mmp: 270, cnstl: 61, cluster: 7, }, { year: 2001, smp: 57, mmp: 261, cnstl: 157, cluster: 45, }, { year: 2003, smp: 0, mmp: 154, cnstl: 121, cluster: 211, }, { year: 2005, smp: 0, mmp: 97, cnstl: 39, cluster: 382, }, { year: 2007, smp: 0, mmp: 83, cnstl: 3, cluster: 437, }, ]; export const seriesTypeLabel = { 'aria-label': 'Series Type' };
<!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="https://cdn3.devexpress.com/jslib/23.2.5/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>
.options { padding: 20px; background-color: rgba(191, 191, 191, 0.15); margin-top: 20px; } .option { margin-top: 10px; } .caption { font-size: 18px; font-weight: 500; } .option > span { margin-right: 10px; } .option > .dx-widget { display: inline-block; vertical-align: middle; }