- Line chart
- Examples
- Area chart
- Extra options & subtitle
- Hiding the legends
- Zooming and panning
- Datasets & datapoints
- Extrapolated/missing data
- Annotations
- Changing data
- Custom plugins
- Mixed charts (Line + Bar)
- Timeseries data and interpolation
- Massive timeseries data
- CSS variables as colors
- Custom legend positioning
- Importing
- Properties
- Parts
Line Chart
<mo-line-chart> | MOLineChart
Line charts are used to represent data points in a series.
Line chart is used to display continuous data, and it is often used to visualize a trend in data over time. By overlaying multiple data entries in one chart, it can present the relationship between values.
<mo-line-chart subtitle="Data from Weather Spark" title="Avg. temp. by month" id="first-example"></mo-line-chart> <script> const chart = document.querySelector('#first-example'); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const stockholm = [-2, -2, 1, 5, 11, 15, 18, 16, 12, 7, 3, -1]; const paris = [4, 5, 8, 11, 14, 18, 20, 20, 16, 12, 8, 5]; const rome = [7, 8, 11, 13, 18, 22, 25, 25, 21, 17, 12, 8]; const datasets = [ { label: 'Helsinki', data: helsinki, tension: 0.4 }, { label: 'Stockholm', data: stockholm, tension: 0.4 }, { label: 'Paris', data: paris, tension: 0.4 }, { label: 'Rome', data: rome, tension: 0.4 } ]; chart.labels = labels; chart.datasets = datasets; </script>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const stockholm = [-2, -2, 1, 5, 11, 15, 18, 16, 12, 7, 3, -1]; const paris = [4, 5, 8, 11, 14, 18, 20, 20, 16, 12, 8, 5]; const rome = [7, 8, 11, 13, 18, 22, 25, 25, 21, 17, 12, 8]; const datasets = [ { label: 'Helsinki', data: helsinki, tension: 0.4 }, { label: 'Stockholm', data: stockholm, tension: 0.4 }, { label: 'Paris', data: paris, tension: 0.4 }, { label: 'Rome', data: rome, tension: 0.4 } ]; const App = () => ( <MOLineChart datasets={datasets} labels={labels} subtitle="Data from Weather Spark" title="Avg. temp. by month" ></MOLineChart> );
The charts in Modes UI are based on Chart.js, and thus most of the customization can be
done via the options
property. Check the
full Chart.js documentation here.
Examples
Area chart
A line chart can also function as an area chart. Adding the boolean property area
to the chart
and configuring the datasets to fill the area is enough, as shown in the example. For all fill options,
check
Chart.js documentation.
<mo-line-chart area subtitle="Data from Weather Spark" title="Avg. temp. by month" id="area"></mo-line-chart> <script> const chart = document.querySelector('#area'); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const paris = [4, 5, 8, 11, 14, 18, 20, 20, 16, 12, 8, 5]; const datasets = [ { label: 'Helsinki', data: helsinki, tension: 0.4, fill: 'start' }, { label: 'Paris', data: paris, tension: 0.4, fill: 'start' } ]; const extraOptions = { scales: { y: { min: -10, max: 25 } } }; chart.labels = labels; chart.options = extraOptions; chart.datasets = datasets; </script>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const paris = [4, 5, 8, 11, 14, 18, 20, 20, 16, 12, 8, 5]; const datasets = [ { label: 'Helsinki', data: helsinki, tension: 0.4, fill: 'start' }, { label: 'Paris', data: paris, tension: 0.4, fill: 'start' } ]; const extraOptions = { scales: { y: { min: -10, max: 25 } } }; const App = () => ( <MOLineChart area datasets={datasets} labels={labels} options={extraOptions} subtitle="Data from Weather Spark" title="Avg. temp. by month" ></MOLineChart> );
Area charts are typically used with just one dataset, and we recommend to use only one or two. They can be used to highlight changes in trend to a particular key performance indicator.
Extra options & subtitle
The line chart comes with a ton of extra options that can be configured, courtery of Chart.js. In this case
the chart has multiple y axes and a subtitle
.
By default the charts have an aspect ratio of 1:2, and they maintain this aspect ratio. You can use the
option maintainAspectRatio: false
if you wish to use another aspect ratio, or specify a
specific one using the aspectRatio
option.
<mo-line-chart subtitle="Data from Weather Spark" title="Climate in Helsinki" id="options"></mo-line-chart> <script> const chart = document.querySelector('#options'); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const temps = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const rainfalls = [19.7, 13.7, 17.6, 28.0, 35.5, 47.1, 44.1, 53.2, 52.6, 56.3, 45.8, 27.4]; const datasets = [ { label: 'Temp.', data: temps, yAxisID: 'A' }, { label: 'Rainfall', data: rainfalls, yAxisID: 'B' } ]; const extraOptions = { maintainAspectRatio: false, scales: { y: { display: false }, A: { grid: { borderColor: '#6730BF' }, display: true, title: { display: true, text: 'Temperature', color: '#6730BF', font: { family: 'GT-Eesti' } }, type: 'linear', position: 'left', ticks: { callback: function (value, index, ticks) { return value + ' °C'; } } }, B: { grid: { borderColor: '#16A889' }, type: 'linear', position: 'right', title: { display: true, text: 'Rainfall', color: '#16A889', font: { family: 'GT-Eesti' } }, ticks: { callback: function (value, index, ticks) { return value + ' mm'; } } } } }; chart.labels = labels; chart.datasets = datasets; chart.options = extraOptions; </script> <style> #options::part(base) { position: relative; max-height: 200px; } #options::part(canvas) { max-height: 200px; } </style>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; const css = ` #options::part(base) { position: relative; max-height: 200px; } #options::part(canvas) { max-height: 200px; } `; const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const temps = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const rainfalls = [19.7, 13.7, 17.6, 28.0, 35.5, 47.1, 44.1, 53.2, 52.6, 56.3, 45.8, 27.4]; const datasets = [ { label: 'Temp.', data: temps, yAxisID: 'A', borderWidth: 1.5 }, { label: 'Rainfall', data: rainfalls, yAxisID: 'B', borderWidth: 1.5 } ]; const extraOptions = { maintainAspectRatio: false, scales: { y: { display: false }, A: { grid: { borderColor: '#6730BF', }, display: true, title: { display: true, text: 'Temperature', color: '#6730BF', font: { family: 'GT-Eesti' } }, type: 'linear', position: 'left', ticks: { callback: function (value, index, ticks) { return value + ' °C'; } } }, B: { grid: { borderColor: '#16A889' }, type: 'linear', position: 'right', title: { display: true, text: 'Rainfall', color: '#16A889', font: { family: 'GT-Eesti' } }, ticks: { callback: function (value, index, ticks) { return value + ' mm'; } } } } }; const App = () => ( <MOLineChart options={extraOptions} labels={labels} subtitle="Data from Weather Spark" title="Avg. temp. by month" datasets={datasets} ></MOLineChart> <style>{css}</style> );
Note that custom colors defined in the options object will not automatically translate into dark mode variants, and chart.js does not accept CSS variables natively.
Hiding the legends
You can also use the options
property to hide the legends of the line chart.
<mo-line-chart subtitle="Data from Weather Spark" title="Avg. temp. by month" id="legend-example"></mo-line-chart> <script> const chart = document.querySelector('#legend-example'); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const stockholm = [-2, -2, 1, 5, 11, 15, 18, 16, 12, 7, 3, -1]; const paris = [4, 5, 8, 11, 14, 18, 20, 20, 16, 12, 8, 5]; const rome = [7, 8, 11, 13, 18, 22, 25, 25, 21, 17, 12, 8]; const options = { plugins: { htmlLegend: { hideLegends: true } } } const datasets = [ { label: 'Helsinki', data: helsinki, tension: 0.4 }, { label: 'Stockholm', data: stockholm, tension: 0.4 }, { label: 'Paris', data: paris, tension: 0.4 }, { label: 'Rome', data: rome, tension: 0.4 } ]; chart.options = options; chart.labels = labels; chart.datasets = datasets; </script>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const stockholm = [-2, -2, 1, 5, 11, 15, 18, 16, 12, 7, 3, -1]; const paris = [4, 5, 8, 11, 14, 18, 20, 20, 16, 12, 8, 5]; const rome = [7, 8, 11, 13, 18, 22, 25, 25, 21, 17, 12, 8]; const options = { plugins: { htmlLegend: { hideLegends: true } } } const datasets = [ { label: 'Helsinki', data: helsinki, tension: 0.4 }, { label: 'Stockholm', data: stockholm, tension: 0.4 }, { label: 'Paris', data: paris, tension: 0.4 }, { label: 'Rome', data: rome, tension: 0.4 } ]; const App = () => ( <MOLineChart datasets={datasets} options={options} labels={labels} subtitle="Data from Weather Spark" title="Avg. temp. by month" ></MOLineChart> );
Zooming and panning
The line chart supports zooming and panning, and it can be enabled by simply enabling the property
zoomable
. Use the zoomOptions
attribute to customize the zooming functionality.
<mo-line-chart zoomable title="Financial results" id="zooming"></mo-line-chart> <mo-button id="reset-zoom-btn">Reset zoom</mo-button> <script> const chart = document.querySelector('#zooming'); const resetBtn = document.querySelector('#reset-zoom-btn'); const labels = ['Q1', 'Q2', 'Q3', 'Q4']; const data = [12, 19, 3, 5]; const data2 = [7, 11, 6, 2]; const data3 = [9, 14, 7, 3]; const data4 = [10, 20, 15, 7]; const datasets = [ { label: 'Apple', data: data }, { label: 'OnePlus', data: data2 }, { label: 'Nokia', data: data3 }, { label: 'Samsung', data: data4 } ]; resetBtn.addEventListener('click', () => { chart.resetZoom(); }); chart.labels = labels; chart.datasets = datasets; </script>
import { MOLineChart, MOButton } from '@metsooutotec/modes-web-components/dist/react'; const lineChartRef = useRef(null); const labels = ['Q1', 'Q2', 'Q3', 'Q4']; const data = [12, 19, 3, 5]; const data2 = [7, 11, 6, 2]; const data3 = [9, 14, 7, 3]; const data4 = [10, 20, 15, 7]; const datasets = [ { label: 'Apple', data: data }, { label: 'OnePlus', data: data2 }, { label: 'Nokia', data: data3 }, { label: 'Samsung', data: data4 } ]; const resetZoom = () => { lineChartRef.resetZoom(); }; const App = () => ( <> <MOLineChart ref={lineChartRef} zoomable datasets={datasets} labels={labels} title="Financial results" ></MOLineChart> <MOButton onClick={resetZoom}>Reset zoom</MOButton> </> );
Find all the zooming options in the plugin’s documentation.
Datasets & datapoints
Supplying the line chart with multiple data sets will result in multiple lines, with varying colors and data point shapes.
<mo-line-chart showDatapoints title="Financial results" id="multiple"></mo-line-chart> <script> const chart = document.querySelector('#multiple'); const labels = ['Q1', 'Q2', 'Q3', 'Q4']; const data = [12, 19, 3, 5]; const data2 = [7, 11, 6, 2]; const data3 = [9, 14, 7, 3]; const data4 = [10, 20, 15, 7]; const datasets = [ { label: 'Apple', data: data }, { label: 'OnePlus', data: data2 }, { label: 'Nokia', data: data3 }, { label: 'Samsung', data: data4 } ]; chart.labels = labels; chart.datasets = datasets; </script>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; const labels = ['Q1', 'Q2', 'Q3', 'Q4']; const data = [12, 19, 3, 5]; const data2 = [7, 11, 6, 2]; const data3 = [9, 14, 7, 3]; const data4 = [10, 20, 15, 7]; const datasets = [ { label: 'Apple', data: data }, { label: 'OnePlus', data: data2 }, { label: 'Nokia', data: data3 }, { label: 'Samsung', data: data4 } ]; const App = () => ( <MOLineChart showDatapoints datasets={datasets} labels={labels} title="Financial results"></MOLineChart> );
Extrapolated/missing data
Missing data should be indicated as either NaN
or undefined
this the regular data
that is given to the chart. Extrapolated data should be given in its own extrapolatedData
array
in the individual dataset objects inside datasets
. This separate set of data will then be
internally appended to the regular data and styled differently.
<mo-line-chart extrapolation subtitle="With some missing data" title="Avg. temp. by month" id="extrapolation" ></mo-line-chart> <script> const chart = document.querySelector('#extrapolation'); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6]; const stockholm = [-2, -2, 1, 5, 11, 15, 18, 16, 12, 7]; const paris = [4, 5, 8, 11, 14, 18, NaN, 20, 16]; const rome = [7, 8, 11, 13, undefined, 22, 25, 25, 21, 17]; const datasets = [ { label: 'Helsinki', data: helsinki, extrapolatedData: [2, -2] }, { label: 'Stockholm', data: stockholm, extrapolatedData: [3, -1] }, { label: 'Paris', data: paris, extrapolatedData: [12, 8, 5] }, { label: 'Rome', data: rome, extrapolatedData: [12, 8] } ]; chart.labels = labels; chart.datasets = datasets; </script>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; const chart = document.querySelector('#extrapolation'); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6]; const stockholm = [-2, -2, 1, 5, 11, 15, 18, 16, 12, 7]; const paris = [4, 5, 8, 11, 14, 18, NaN, 20, 16]; const rome = [7, 8, 11, 13, undefined, 22, 25, 25, 21, 17]; const datasets = [ { label: 'Helsinki', data: helsinki, extrapolatedData: [2, -2] }, { label: 'Stockholm', data: stockholm, extrapolatedData: [3, -1] }, { label: 'Paris', data: paris, extrapolatedData: [12, 8, 5] }, { label: 'Rome', data: rome, extrapolatedData: [12, 8] } ]; const App = () => ( <MOLineChart extrapolation subtitle="With some missing data" title="Avg. temp. by month" datasets={datasets} labels={labels} ></MOLineChart> );
Note that the combined length of the regular dataset.data
array and
dataset.extrapolatedData
array must be equal to the length of the labels
array.
Annotations
The charts in Modes UI can include annotations in the form of lines and boxes. See the full documentation for the plugin here.
<mo-line-chart title="Financial results" id="annotation"></mo-line-chart> <script> const chart = document.querySelector('#annotation'); const labels = ['Q1', 'Q2', 'Q3', 'Q4']; const data = [12, 19, 3, 5]; const data2 = [7, 11, 6, 2]; const data3 = [9, 14, 7, 3]; const data4 = [10, 20, 15, 7]; const datasets = [ { label: 'Apple', data: data }, { label: 'OnePlus', data: data2 }, { label: 'Nokia', data: data3 }, { label: 'Samsung', data: data4 } ]; const options = { plugins: { annotation: { annotations: { line1: { type: 'line', yMin: 15, yMax: 15, borderColor: '#ff2a45', borderWidth: 1, borderDash: [5, 2] }, line2: { type: 'line', yMin: 10, yMax: 10, borderColor: '#FB9613', borderWidth: 1, borderDash: [5, 2] } } } } }; chart.options = options; chart.labels = labels; chart.datasets = datasets; </script>
Changing data
The line chart will automatically update when the data changes, along with animations.
<mo-line-chart showDatapoints title="Line chart" id="animations"></mo-line-chart> <mo-divider></mo-divider> <mo-button id="add-data">Add data</mo-button> <mo-button id="add-dataset">Add dataset</mo-button> <mo-button variant="secondary" id="reset-data">Reset data</mo-button> <script> const chart = document.querySelector('#animations'); const addData = document.querySelector('#add-data'); const addDataset = document.querySelector('#add-dataset'); const resetData = document.querySelector('#reset-data'); // set initial data let labels = ['0', '1', '2', '3']; let data = [12, 19, 3, 5]; let datasets = [{ label: 'Original dataset with really long text', data: data }]; let index = 4; let datasetIndex = 1; chart.labels = labels; chart.datasets = datasets; // add data point(s) addData.addEventListener('click', () => { labels.push(`${index}`); for (let i = 0; i < datasets.length; i++) { datasets[i].data.push(Math.max(1, Math.floor(Math.random() * 20))); } index++; const newDatasets = [...datasets]; chart.datasets = newDatasets; }); // add new dataset addDataset.addEventListener('click', () => { datasets.push({ label: `New dataset #${datasetIndex}`, data: Array.from({ length: labels.length }, () => Math.max(1, Math.floor(Math.random() * 20))) }); index++; datasetIndex++; const newDatasets = [...datasets]; chart.datasets = newDatasets; }); // reset to initial data resetData.addEventListener('click', () => { data = [12, 19, 3, 5]; labels = ['1', '2', '3', '4']; datasets = [{ label: 'Original dataset', data: data }]; chart.datasets = datasets; chart.labels = labels; index = 4; }); </script>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; const [labels, setLabels] = useState(['0', '1', '2', '3']); const data = [12, 19, 3, 5]; const [datasets, setDatasets] = useState([{ label: 'Original dataset', data: data }]); const [index, setIndex] = useState(4); const [datasetIndex, setDatasetIndex] = useState(1); const resetData = () => { setDatasets([{ label: 'Original dataset', data: [12, 19, 3, 5] }]); setLabels(['0', '1', '2', '3']); setDatasetIndex(1); setIndex(4); }; const addData = () => { setLabels([...labels, `${index}`]); for (const i = 0; i < datasets.length; i++) { datasets[i].data.push(Math.max(1, Math.floor(Math.random() * 20))); } setIndex(index + 1); const newDatasets = [...datasets]; setDatasets(newDatasets); }; const addDataset = () => { datasets.push({ label: `New dataset #${datasetIndex}`, data: Array.from({ length: labels.length }, () => Math.max(1, Math.floor(Math.random() * 20))) }); setIndex(index + 1); setDatasetIndex(datasetIndex + 1); const newDatasets = [...datasets]; setDatasets(newDatasets); }; const App = () => ( <> <MOLineChart showDatapoints labels={labels} title="Changing data" datasets={datasets}></MOLineChart> <MODivider></MODivider> <div> <MOButton onClick={addData}>Add data</MOButton> <MOButton onClick={addDataset}>Add dataset</MOButton> <MOButton onClick={resetData} variant="secondary"> Reset data </MOButton> </div> </> );
Custom plugins
Chart.js allows for custom plugins to further customize and add functionality to the chart. Use the
custom-plugins
attribute to set your own custom plugins. Use the options attribute to customize
plugin arguments.
not hovering
<mo-label>Hover status</mo-label> <br/> <span id="hover-status">not hovering</span> <br/><br/> <mo-line-chart title="Custom Plugin Example" id="custom-plugin"></mo-line-chart> <script> const chart = document.querySelector('#custom-plugin'); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const data = [12, 19, 3, 5, 2, 3, 9, 10, 15, 20, 25, 30]; const datasets = [{ label: 'Sample Data', data: data }]; const customPlugin = { id: 'hoverOutPlugin', afterEvent: (chart, args, options) => { const statusSpan = document.querySelector('#hover-status'); const event = args.event; const mouseOutMessage = options.msg; if (event.type === 'mouseout') { statusSpan.classList.remove('hovering'); statusSpan.textContent = 'not hovering' } else { statusSpan.classList.add('hovering'); statusSpan.textContent = 'hovering' } } }; const options = { plugins: { hoverOutPlugin: { msg: 'Hovered out of chart.' } } } chart.labels = labels; chart.datasets = datasets; chart.options = options; chart.customPlugins = [customPlugin]; </script> <style> #hover-status { background-color: var(--mo-color-status-alert-container); border: 1px solid var(--mo-color-status-alert); color: var(--mo-color-status-alert-on-container); padding: 0.25rem 0.5rem; } #hover-status.hovering { background-color: var(--mo-color-status-success-container); color: var(--mo-color-status-success-on-container); border-color: var(--mo-color-status-success); } </style>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const data = [12, 19, 3, 5, 2, 3, 9, 10, 15, 20, 25, 30]; const datasets = [{ label: 'Sample Data', data: data }]; const customPlugin = { id: 'hoverOutPlugin', afterEvent: (chart, args, options) => { const statusSpan = document.querySelector('#hover-status'); const event = args.event; const mouseOutMessage = options.msg; if (event.type === 'mouseout') { statusSpan.classList.remove('hovering'); statusSpan.textContent = 'not hovering' } else { statusSpan.classList.add('hovering'); statusSpan.textContent = 'hovering' } } }; const options = { plugins: { hoverOutPlugin: { msg: 'Hovered out of chart.' } } } const App = () => ( <MOLineChart datasets={datasets} labels={labels} customPlugins={[customPlugin]} options={options} title="Custom Plugin Example" ></MOLineChart> );
Mixed charts (Line + Bar)
Multiple different charts can be rendered in the same view and mixed by defining an individual
type
for each dataset.
<mo-line-chart title="Financial results" id="mixed"></mo-line-chart> <script> const chart = document.querySelector('#mixed'); const labels = ['Q1', 'Q2', 'Q3', 'Q4']; const data = [12, 19, 3, 5]; const data2 = [7, 11, 6, 2]; const data3 = [9, 14, 7, 3]; const datasets = [ { label: 'Apple', data: data }, { label: 'Nokia', data: data3 }, { label: 'OnePlus', data: data2, type: 'bar' } ]; chart.labels = labels; chart.datasets = datasets; </script>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; const labels = ['Q1', 'Q2', 'Q3', 'Q4']; const data = [12, 19, 3, 5]; const data2 = [7, 11, 6, 2]; const data3 = [9, 14, 7, 3]; const datasets = [ { label: 'Apple', data: data }, { label: 'Nokia', data: data3 }, { label: 'OnePlus', data: data2, type: 'bar' } ]; const App = () => <MOLineChart datasets={datasets} labels={labels} title="Financial results"></MOLineChart>;
Timeseries data and interpolation
The line chart can also show timeseries data, to do this set the options object as shown here. Cubic
interpolation can be enabled by adding a tension
property to the dataset.
<mo-line-chart zoomable title="Timeseries data" id="points"></mo-line-chart> <script> const chart = document.querySelector('#points'); function makeSeries(seriesCount, points) { return Array(seriesCount) .fill({ data: [] }) .map(s => { return { data: Array(points) .fill(1) .map((d, i) => ({ x: new Date(Date.now() - i * 24 * 3600000), y: Math.max(250, Math.random() * 3000) })) }; }); } const data = makeSeries(3, 20); const options = { scales: { x: { position: 'bottom', type: 'time', ticks: { autoSkip: true, autoSkipPadding: 50, maxRotation: 0 }, time: { displayFormats: { hour: 'HH:mm', minute: 'HH:mm', second: 'HH:mm:ss' } } } } }; const datasets = [ { label: 'Random data', data: data[0].data, tension: 0.4 }, { label: 'Random data', data: data[1].data, tension: 0.4 }, { label: 'Random data', data: data[2].data, tension: 0.4 } ]; chart.options = options; chart.datasets = datasets; </script>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; function makeSeries(seriesCount, points) { return Array(seriesCount) .fill({ data: [] }) .map(s => { return { data: Array(points) .fill(1) .map((d, i) => ({ x: new Date(Date.now() - i * 24 * 3600000), y: Math.max(250, Math.random() * 3000) })) }; }); } const data = makeSeries(3, 15); const options = { scales: { x: { position: 'bottom', type: 'time', ticks: { autoSkip: true, autoSkipPadding: 50, maxRotation: 0 }, time: { displayFormats: { hour: 'HH:mm', minute: 'HH:mm', second: 'HH:mm:ss' } } } } }; const datasets = [ { label: 'Random data', data: data[0].data, tension: 0.4 }, { label: 'Random data', data: data[1].data, tension: 0.4 }, { label: 'Random data', data: data[2].data, tension: 0.4 } ]; const App = () => <MOLineChart datasets={datasets} options={options} title="Timeseries data "></MOLineChart>;
Massive timeseries data
Chart.js charts are performant and capable of showing data from massive datasets. This example can have thousands of datapoints, and renders practically instantly. Decimation is a recommended practice to reduce visually redundant data points while simultaneously improving performance. In order to enable decimation, parsing must be disabled, which means the time data must be given as milliseconds from epoch (Jan. 1, 1970).
Amount of points:
<mo-line-chart subtitle="With decimation to 250 samples" title="Massive data" id="massive"></mo-line-chart> <mo-divider></mo-divider> <div style="display: flex; gap: 16px; align-items: center; justify-content: space-between; flex-wrap: wrap"> <div style="display: flex; gap: 16px; align-items: center;"> <p style="font-family: var(--mo-font-sans)">Amount of points:</p> <mo-select id="point-select" value="500" style="width: 250px"> <mo-option value="500">500</mo-option> <mo-option value="2500">2,500</mo-option> <mo-option value="5000">5,000</mo-option> <mo-option value="10000">10,000</mo-option> <mo-option value="100000">100,000</mo-option> </mo-select> </div> <mo-switch id="decimation-toggle"> <mo-icon name="ok" slot="suffix"></mo-icon> Toggle decimation </mo-switch> </div> <script> const chart = document.querySelector('#massive'); function makeSeries(seriesCount, points) { return Array(seriesCount) .fill({ data: [] }) .map(s => { return { data: Array(points) .fill(1) .map((d, i) => ({ x: i * 3600000, y: Math.max(250, Math.random() * 3000) })) }; }); } let data = makeSeries(1, 500); const options = { // Turn off animations and data parsing for performance (+ decimation) animation: false, parsing: false, plugins: { decimation: { enabled: false, algorithm: 'min-max' } }, scales: { x: { type: 'time', time: { unit: 'day' } } } }; const toggle = document.querySelector('#decimation-toggle'); const select = document.querySelector('#point-select'); toggle.addEventListener('mo-change', event => { if (event.target.checked) { chart.chart.options.plugins.decimation.enabled = true; chart.chart.options.plugins.decimation.algorithm = 'lttb'; chart.chart.options.plugins.decimation.samples = 250; chart.chart.options.plugins.decimation.threshold = 250; } else { chart.chart.options.plugins.decimation.enabled = false; } chart.chart.update(); }); select.addEventListener('mo-change', event => { const points = parseInt(event.target.value); data = makeSeries(1, parseInt(event.target.value)); const datasets = [{ label: `${points} points`, data: data[0].data, borderWidth: 1 }]; toggle.checked = false; chart.datasets = datasets; }); // set smaller borderWidth for clarity const datasets = [{ label: '500 points', data: data[0].data, borderWidth: 1 }]; chart.datasets = datasets; chart.options = options; </script>
import { MOLineChart, MOIcon, MOSwitch, MODivider, MOSelect, MOOption } from '@metsooutotec/modes-web-components/dist/react'; function makeSeries(seriesCount, points) { return Array(seriesCount) .fill({ data: [] }) .map(s => { return { data: Array(points) .fill(1) .map((d, i) => ({ x: i * 3600000, y: Math.max(250, Math.random() * 3000) })) }; }); } var data = makeSeries(1, 500); const [datasets, setDatasets] = useState([{ label: '500 points', data: data[0].data, borderWidth: 1 }]); const [selectValue, setSelectValue] = useState('500'); const [options, setOptions] = useState({ // Turn off animations and data parsing for performance (+ decimation) animation: false, parsing: false, plugins: { decimation: { enabled: false, algorithm: 'min-max' } }, scales: { x: { type: 'time', time: { unit: 'day' } } } }); const toggleDecimation = event => { const optionsCopy = { ...options }; if (event.target.checked) { optionsCopy.plugins.decimation.enabled = true; optionsCopy.plugins.decimation.algorithm = 'lttb'; optionsCopy.plugins.decimation.samples = 250; optionsCopy.plugins.decimation.threshold = 250; } else { optionsCopy.plugins.decimation.enabled = false; } setOptions(optionsCopy); }; const updateData = amount => { const newData = makeSeries(1, amount); const newDatasets = [{ label: `${amount} points`, data: newData[0].data, borderWidth: 1 }]; setSelectValue(`${amount}`); setDatasets(newDatasets); }; const App = () => { <> <MOLineChart title="Massive timeseries data" options={options} datasets={datasets}></MOLineChart> <MODivider></MODivider> <div style={{ display: 'flex', gap: '16px', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap' }} > <div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}> <p style={{ fontFamily: 'var(--mo-font-sans)' }}>Amount of points:</p> <MOSelect onMoChange={event => updateData(parseInt(event.target.value))} value={selectValue} style={{ width: '250px' }} > <MOOption value="500">500</MOOption> <MOOption value="2500">2,500</MOOption> <MOOption value="5000">5,000</MOOption> <MOOption value="10000">10,000</MOOption> <MOOption value="100000">100,000</MOOption> </MOSelect> </div> <MOSwitch onMoChange={event => toggleDecimation(event)}> <MOIcon name="ok" slot="suffix"></MOIcon> Toggle decimation </MOSwitch> </div> </>; };
Showing thousands of points in the chart at a time is not recommended. Refer to the
performance page
in Chart.js documentation for ways to improve performance on even larger datasets. Avoid using
showDatapoints
, and set the borderWidth
to 1
for each dataset to
prevent overlap in charts with lots of data.
CSS variables as colors
You can also assign existing CSS color variables as the colors for the data. Any variables found in the theme files should function here (assuming you have imported the css file your project).
<mo-line-chart subtitle="Data from Weather Spark" title="Avg. temp. by month" id="css-colors"></mo-line-chart> <script> const chart = document.querySelector('#css-colors'); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const stockholm = [-2, -2, 1, 5, 11, 15, 18, 16, 12, 7, 3, -1]; const paris = [4, 5, 8, 11, 14, 18, 20, 20, 16, 12, 8, 5]; const datasets = [ { label: 'Helsinki', data: helsinki, tension: 0.4, borderColor: 'var(--mo-color-data-10)' }, { label: 'Stockholm', data: stockholm, tension: 0.4, borderColor: '--mo-color-data-11' }, { label: 'Paris', data: paris, tension: 0.4, borderColor: '--mo-color-data-12' } ]; chart.labels = labels; chart.options = options; chart.datasets = datasets; </script>
import { MOLineChart } from '@metsooutotec/modes-web-components/dist/react'; const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const stockholm = [-2, -2, 1, 5, 11, 15, 18, 16, 12, 7, 3, -1]; const paris = [4, 5, 8, 11, 14, 18, 20, 20, 16, 12, 8, 5]; const datasets = [ { label: 'Helsinki', data: helsinki, tension: 0.4, borderColor: 'var(--mo-color-data-10)' }, { label: 'Stockholm', data: stockholm, tension: 0.4, borderColor: '--mo-color-data-11' }, { label: 'Paris', data: paris, tension: 0.4, borderColor: '--mo-color-data-12' } ]; const App = () => ( <MOLineChart datasets={datasets} labels={labels} subtitle="Data from Weather Spark" title="Avg. temp. by month" ></MOLineChart> );
Variables can be given either as var(--mo-color-data-12)
or --mo-color-data-12
.
Custom legend positioning
The legend can be placed next to the chart using the legendPosition
and
legendAlignment
attributes. See the example below on different permutations.
<div style="display: flex; gap: 16px;"> <mo-select id="pos-select" value="right"> <mo-option value="top">Top</mo-option> <mo-option value="left">Left</mo-option> <mo-option value="bottom">Bottom</mo-option> <mo-option value="right">Right</mo-option> </mo-select> <mo-select id="align-select" value="start"> <mo-option value="start">Start</mo-option> <mo-option value="end">End</mo-option> </mo-select> </div> <mo-divider></mo-divider> <mo-line-chart legendPosition="right" legendAlignment="start" subtitle="Data from Weather Spark" title="Avg. temp. by month" id="last-example" ></mo-line-chart> <script> const chart = document.querySelector('#last-example'); const posSelect = document.querySelector('#pos-select'); const alignSelect = document.querySelector('#align-select'); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const stockholm = [-2, -2, 1, 5, 11, 15, 18, 16, 12, 7, 3, -1]; const paris = [4, 5, 8, 11, 14, 18, 20, 20, 16, 12, 8, 5]; const rome = [7, 8, 11, 13, 18, 22, 25, 25, 21, 17, 12, 8]; posSelect.addEventListener('mo-change', e => { const newPos = e.target.value; chart.legendPosition = newPos; }); alignSelect.addEventListener('mo-change', e => { const newAlign = e.target.value; chart.legendAlignment = newAlign; }); const datasets = [ { label: 'Helsinki', data: helsinki, tension: 0.4 }, { label: 'Stockholm', data: stockholm, tension: 0.4 }, { label: 'Paris', data: paris, tension: 0.4 }, { label: 'Rome', data: rome, tension: 0.4 } ]; chart.labels = labels; chart.datasets = datasets; </script>
import { MOLineChart, MODivider, MOSelect, MOOption } from '@metsooutotec/modes-web-components/dist/react'; const lineChartRef = useRef(null); const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const helsinki = [-4, -5, -1, 4, 10, 14, 18, 16, 11, 6, 2, -2]; const stockholm = [-2, -2, 1, 5, 11, 15, 18, 16, 12, 7, 3, -1]; const paris = [4, 5, 8, 11, 14, 18, 20, 20, 16, 12, 8, 5]; const rome = [7, 8, 11, 13, 18, 22, 25, 25, 21, 17, 12, 8]; const updatePos = e => { lineChartRef.legendPosition = e.target.value; }; const updateAlign = e => { lineChartRef.legendAlignment = e.target.value; }; const datasets = [ { label: 'Helsinki', data: helsinki, tension: 0.4 }, { label: 'Stockholm', data: stockholm, tension: 0.4 }, { label: 'Paris', data: paris, tension: 0.4 }, { label: 'Rome', data: rome, tension: 0.4 } ]; const App = () => ( <> <div style={{ display: 'flex', gap: '16px' }}> <MOSelect onMoChange={updatePos} value="right"> <MOOption value="top">Top</MOOption> <MOOption value="left">Left</MOOption> <MOOption value="bottom">Bottom</MOOption> <MOOption value="right">Right</MOOption> </MOSelect> <MOSelect onMoChange={updateAlign} value="start"> <MOOption value="start">Start</MOOption> <MOOption value="end">End</MOOption> </MOSelect> </div> <MODivider></MODivider> <MOLineChart datasets={datasets} labels={labels} legendPosition="right" legendAlignment="start" subtitle="Data from Weather Spark" title="Avg. temp. by month" ref={lineChartRef} ></MOLineChart> </> );
Importing
If you’re using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use any of the following snippets to cherry pick this component.
To import this component using a bundler:
import '@metsooutotec/modes-web-components/dist/components/line-chart/line-chart.js';
To import this component as a React component:
import MOLineChart from '@metsooutotec/modes-web-components/dist/react/line-chart/';
To import this component using a script tag:
<script type="module" src="https://modes-web.metso.com/dist/components/cdn/components/line-chart/line-chart.js"></script>
Properties
Name | Description | Reflects | Type | Default |
---|---|---|---|---|
canvas
|
Query for the canvas element instantiated in the html template. |
HTMLCanvasElement
|
- | |
type
|
Type of chart. |
ChartType
|
'line'
|
|
chart
|
Reference to the chart itself. |
Chart
|
- | |
datasets
|
Datasets for the chart |
|
LineChartDataset[]
|
[]
|
labels
|
Labels to show on the x-axis. |
string[]
|
[]
|
|
title
|
Title to be shown above the chart. |
string
|
''
|
|
subtitle
|
Subtitle to be shown above the chart, but below title. |
string
|
''
|
|
legendAlignment
|
Alignment of the legends. |
'start' | 'end'
|
'start'
|
|
legendPosition
|
Position of the legends. |
'bottom' | 'right' | 'left' | 'top'
|
'bottom'
|
|
options
|
Additional options for the chart. |
|
ChartOptions
|
{}
|
zoomOptions
|
Options for the zoom plugin. |
|
ZoomPluginOptions
|
{ pan: { enabled: true, mode: 'xy', modifierKey: 'ctrl' }, zoom: { drag: { enabled: true }, mode:
'xy' } }
|
showDatapoints
|
Show datapoints. |
|
boolean
|
false
|
zoomable
|
Enables zooming on the chart. |
|
boolean
|
false
|
area
|
Area chart. |
|
boolean
|
false
|
extrapolation
|
Show dashed line where data is missing. |
|
boolean
|
false
|
thinLines
|
Make likes between datapoints thinner. Should be used with massive data. |
|
boolean
|
false
|
customPlugins
custom-plugins
|
Use this property to add custom plugins to the created chart.js instance |
Plugin[]
|
[]
|
|
updateComplete |
A read-only promise that resolves when the component has finished updating. |
Learn more about attributes and properties.
Parts
Name | Description |
---|---|
base |
The div containing the canvas element. |
canvas |
The canvas element the chart is rendered in. |
legends |
The custom legends below the chart. |
Learn more about customizing CSS parts.