DevExtreme v24.1 is now available.

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

Your search did not match any results.

Multiple Axes

You can display the Chart component with multiple axes for better data visualization. This demo illustrates a chart with two separate axes that display percentage and absolute values.

www.wikipedia.org
Backend API
<template> <DxChart id="chart" :data-source="populationData" palette="Vintage" > <DxCommonSeriesSettings argument-field="year" type="fullstackedbar" /> <DxSeries v-for="continent in continentSources" :key="continent.value" :value-field="continent.value" :name="continent.name" /> <DxSeries axis="total" type="spline" value-field="total" name="Total" color="#008fd8" /> <DxValueAxis> <DxGrid :visible="true"/> </DxValueAxis> <DxValueAxis name="total" position="right" title="Total Population, billions" > <DxGrid :visible="true"/> </DxValueAxis> <DxLegend vertical-alignment="bottom" horizontal-alignment="center" /> <DxExport :enabled="true"/> <DxTooltip :enabled="true" :shared="true" :customize-tooltip="customizeTooltip" > <DxFormat :precision="1" type="largeNumber" /> </DxTooltip> <DxTitle text="Evolution of Population by Continent"/> </DxChart> </template> <script setup lang="ts"> import DxChart, { DxCommonSeriesSettings, DxSeries, DxValueAxis, DxExport, DxLegend, DxTooltip, DxTitle, DxGrid, DxFormat, } from 'devextreme-vue/chart'; import { continentSources, populationData } from './data.ts'; function customizeTooltip(pointInfo) { const items = pointInfo.valueText.split('\n'); const color = pointInfo.point.getColor(); items.forEach((item, index) => { if (item.indexOf(pointInfo.seriesName) === 0) { const element = document.createElement('span'); element.textContent = item; element.style.color = color; element.className = 'active'; items[index] = element.outerHTML; } }); return { text: items.join('\n') }; } </script> <style> #chart { height: 440px; } .active { font-weight: 500; } </style>
window.exports = window.exports || {}; window.config = { transpiler: 'plugin-babel', meta: { '*.vue': { loader: 'vue-loader', }, '*.ts': { loader: 'demo-ts-loader', }, '*.svg': { loader: 'svg-loader', }, 'devextreme/time_zone_utils.js': { 'esModule': true, }, 'devextreme/localization.js': { 'esModule': true, }, 'devextreme/viz/palette.js': { 'esModule': true, }, }, paths: { 'root:': '../../../../', 'npm:': 'https://unpkg.com/', }, map: { 'vue': 'npm:vue@3.2.47/dist/vue.esm-browser.js', 'vue-loader': 'npm:dx-systemjs-vue-browser@1.1.1/index.js', 'demo-ts-loader': 'root:utils/demo-ts-loader.js', 'svg-loader': 'root:utils/svg-loader.js', 'mitt': 'npm:mitt/dist/mitt.umd.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.3/cjs', 'devextreme-vue': 'npm:devextreme-vue@24.1.3/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.8/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', '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-vue': { main: 'index.js', }, 'devextreme': { defaultExtension: '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.13/inferno/package.json', ], babelOptions: { sourceMaps: false, stage0: true, }, }; System.config(window.config);
export const continentSources = [ { value: 'africa', name: 'Africa' }, { value: 'asia', name: 'Asia' }, { value: 'europe', name: 'Europe' }, { value: 'latinamerica', name: 'Latin America & Caribbean' }, { value: 'northamerica', name: 'Northern America' }, { value: 'oceania', name: 'Oceania' }, ]; export const populationData = [{ year: '1750', africa: 106000000, asia: 502000000, europe: 163000000, latinamerica: 16000000, northamerica: 2000000, oceania: 2000000, total: 791000000, }, { year: '1800', africa: 107000000, asia: 635000000, europe: 203000000, latinamerica: 24000000, northamerica: 7000000, oceania: 2000000, total: 978000000, }, { year: '1850', africa: 111000000, asia: 809000000, europe: 276000000, latinamerica: 38000000, northamerica: 26000000, oceania: 2000000, total: 1262000000, }, { year: '1900', africa: 133000000, asia: 947000000, europe: 408000000, latinamerica: 74000000, northamerica: 82000000, oceania: 6000000, total: 1650000000, }, { year: '1950', africa: 229895000, asia: 1403388000, europe: 547287000, latinamerica: 167368000, northamerica: 171614000, oceania: 12675000, total: 2532227000, }, { year: '2000', africa: 811101000, asia: 3719044000, europe: 726777000, latinamerica: 521419000, northamerica: 313289000, oceania: 31130000, total: 6122770000, }, { year: '2050', africa: 2191599000, asia: 5142220000, europe: 719257000, latinamerica: 750956000, northamerica: 446862000, oceania: 55223000, total: 9306128000, }];
import { createApp } from 'vue'; import App from './App.vue'; createApp(App).mount('#app');
<!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.3/css/dx.light.css" /> <script src="https://unpkg.com/typescript@4.9.5/lib/typescript.js"></script> <script type="module"> import * as vueCompilerSFC from "https://unpkg.com/@vue/compiler-sfc@3.4.16/dist/compiler-sfc.esm-browser.js"; window.vueCompilerSFC = vueCompilerSFC; </script> <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.ts"); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"> </div> </div> </body> </html>

To configure a multi-axis chart, follow the steps below:

  1. Create and name value axes. Declare multiple objects in the valueAxis array. Each object configures a value axis. Every value axis should have a unique name.

  2. Bind series to value axes.
    Assign the name of an axis to the series.axis property. If leave the series.axis property unspecified, the series is bound to the axis declared first in the valueAxis array.

In this demo, the first axis is declared without a name and is bound to the first series. The name of the second axis is total and it is bound to the spline series. The position of the second axis is right.