Scatter Plot
<mo-scatter-plot> | MOScatterPlot
Scatter plots are used to display data points on a two-dimensional grid.
<mo-scatter-plot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" title="Scatter plot" id="first-example" ></mo-scatter-plot> <script> const chart = document.querySelector('#first-example'); const dataOne = [ { x: 6, y: -3.1 }, { x: 10, y: -5 }, { x: 3.8, y: -5.5342423 }, { x: 3.5, y: -4.2 }, { x: 6.4, y: -4.9 }, { x: 7.7, y: -3.9 }, { x: 5.8, y: -1.7 } ]; const dataTwo = [ { x: -1, y: 5.7 }, { x: -3.5, y: 4.9 }, { x: -1.5, y: 4.4 }, { x: 4.1, y: 6.9 }, { x: 6.1, y: 4.4 }, { x: 5.1, y: 5.4 }, { x: -2.2, y: 7.1 } ]; const datasets = [ { label: 'Dataset #1', data: dataOne }, { label: 'Dataset #2', data: dataTwo } ]; chart.datasets = datasets; </script>
import { MOScatterPlot } from '@metsooutotec/modes-web-components/dist/react'; const dataOne = [ { x: 0, y: 10 }, { x: 10, y: 5 }, { x: 0.5, y: 5.5 }, { x: 3.5, y: 7.3 }, { x: 6.4, y: 4.9 }, { x: 7.7, y: 5.9 }, { x: 5.8, y: 6.8 } ]; const dataTwo = [ { x: 1, y: 5.7 }, { x: 7.5, y: 4.9 }, { x: 1.5, y: 4.4 }, { x: 4.1, y: 6.9 }, { x: 6.1, y: 4.4 }, { x: 7.1, y: 5.4 }, { x: 6.2, y: 7.1 } ]; const datasets = [ { label: 'Dataset #1', data: dataOne }, { label: 'Dataset #2', data: dataTwo } ]; const App = () => ( <MOScatterPlot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" datasets={datasets} title="Scatter plot" ></MOScatterPlot> );
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.
Unlike the line and bar charts, the scatter plot implementation in Modes UI does not support multiple y-axes.
Examples
Point styling
The accessibility of the scatter plot can be improved by enabling the styledPoints
property,
which will assign a distinct shape to datapoints of each different dataset.
<mo-scatter-plot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" styledPoints title="Scatter plot" subtitle="With point styling" id="styled-points" ></mo-scatter-plot> <script> const chart = document.querySelector('#styled-points'); const dataOne = [ { x: 1.44, y: 9.522 }, { x: 8.953, y: 5.912 }, { x: 0.533221, y: 5.53 }, { x: 3.5, y: 7.35 }, { x: 6.47, y: 4.98 }, { x: 7.723, y: 5.91 }, { x: 5.821123, y: 6.83 } ]; const dataTwo = [ { x: 1.12, y: 5.7 }, { x: 7.5222, y: 4.91 }, { x: 1.55, y: 4.4 }, { x: 4.12, y: 6.911 }, { x: 6.15, y: 4.424 }, { x: 7.1, y: 5.421 }, { x: 6, y: 7.152 } ]; const dataThree = [ { x: 3.123, y: 3.17 }, { x: 2.422, y: 4.11453 }, { x: 1.1, y: 2 }, { x: 2.8235, y: 2.512 }, { x: 9.2, y: 7.411 }, { x: 8.3, y: 7.453 }, { x: 4.432, y: 3.811 } ]; const datasets = [ { label: 'Dataset #1', data: dataOne }, { label: 'Dataset #2', data: dataTwo }, { label: 'Dataset #3', data: dataThree } ]; chart.datasets = datasets; </script>
import { MOScatterPlot } from '@metsooutotec/modes-web-components/dist/react'; const dataOne = [ { x: 1.44, y: 9.522 }, { x: 8.953, y: 5.912 }, { x: 0.533221, y: 5.53 }, { x: 3.5, y: 7.35 }, { x: 6.47, y: 4.98 }, { x: 7.723, y: 5.91 }, { x: 5.821123, y: 6.83 } ]; const dataTwo = [ { x: 1.12, y: 5.7 }, { x: 7.5222, y: 4.91 }, { x: 1.55, y: 4.4 }, { x: 4.12, y: 6.911 }, { x: 6.15, y: 4.424 }, { x: 7.1, y: 5.421 }, { x: 6, y: 7.152 } ]; const dataThree = [ { x: 3.123, y: 3.17 }, { x: 2.422, y: 4.11453 }, { x: 1.1, y: 2 }, { x: 2.8235, y: 2.512 }, { x: 9.2, y: 7.411 }, { x: 8.3, y: 7.453 }, { x: 4.432, y: 3.811 } ]; const datasets = [ { label: 'Dataset #1', data: dataOne }, { label: 'Dataset #2', data: dataTwo }, { label: 'Dataset #3', data: dataThree } ]; const App = () => ( <MOScatterPlot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" styledPoints datasets={datasets} title="Scatter plot" subtitle="With point styling" ></MOScatterPlot> );
Responsive
A scatter plot can fit automatically to parent container. To ensure the chart changes shape and aligns to
its containing box, disable maintainAspectRatio
(enabled by default) and enable
responsive
in the chart options.
<div style="display: flex;"> <div style="width: 40%; height: 400px; border: 1px dashed; padding: 10px;"> <mo-scatter-plot id="responsiveChart1" style="height: 100%;"></mo-scatter-plot> </div> <div style="width: 60%; height: 300px; border: 1px dashed; padding: 10px;"> <mo-scatter-plot id="responsiveChart2" style="height: 100%;"></mo-scatter-plot> </div> </div> <script> ['responsiveChart1', 'responsiveChart2'].forEach(id => { const chart = document.querySelector(`#${id}`); const data = [ { x: 1, y: 3 }, { x: 2, y: 7 }, { x: 3, y: 9 }, { x: 4, y: 2 } ]; const datasets = [{ label: 'Component', data: data }]; chart.options = { maintainAspectRatio: false, responsive: true }; chart.datasets = datasets; }); </script>
import { MOBarChart } from '@metsooutotec/modes-web-components/dist/react'; const labels = ['A1', 'A2', 'A3', 'A4']; const data = [ { x: 1, y: 3 }, { x: 2, y: 7 }, { x: 3, y: 9 }, { x: 4, y: 2 } ]; const datasets = [{ label: 'Component', data: data }]; const options = { maintainAspectRatio: false, responsive: true }; const App = () => <MOScatterPlot datasets={datasets} labels={labels} options={options}></MOScatterPlot>;
Zooming and panning
The scatter plot 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-scatter-plot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" title="Scatter plot" subtitle="With zoom & pan" zoomable id="zooming" ></mo-scatter-plot> <mo-button id="reset-zoom-btn">Reset zoom</mo-button> <script> const chart = document.querySelector('#zooming'); const resetBtn = document.querySelector('#reset-zoom-btn'); const dataOne = [ { x: 1.44, y: 9.522 }, { x: 8.953, y: 5.912 }, { x: 0.533221, y: 5.53 }, { x: 3.5, y: 7.35 }, { x: 6.47, y: 4.98 }, { x: 7.723, y: 5.91 }, { x: 5.821123, y: 6.83 } ]; const dataTwo = [ { x: 1.12, y: 5.7 }, { x: 7.5222, y: 4.91 }, { x: 1.55, y: 4.4 }, { x: 4.12, y: 6.911 }, { x: 6.15, y: 4.424 }, { x: 7.1, y: 5.421 }, { x: 6, y: 7.152 } ]; const dataThree = [ { x: 3.123, y: 3.17 }, { x: 2.422, y: 4.11453 }, { x: 1.1, y: 2 }, { x: 2.8235, y: 2.512 }, { x: 9.2, y: 7.411 }, { x: 8.3, y: 7.453 }, { x: 4.432, y: 3.811 } ]; const datasets = [ { label: 'Dataset #1', data: dataOne }, { label: 'Dataset #2', data: dataTwo }, { label: 'Dataset #3', data: dataThree } ]; resetBtn.addEventListener('click', () => { chart.resetZoom(); }); chart.datasets = datasets; </script>
import { MOScatterPlot } from '@metsooutotec/modes-web-components/dist/react'; import { useRef } from 'react'; const chartRef = useRef(null); const dataOne = [ { x: 1.44, y: 9.522 }, { x: 8.953, y: 5.912 }, { x: 0.533221, y: 5.53 }, { x: 3.5, y: 7.35 }, { x: 6.47, y: 4.98 }, { x: 7.723, y: 5.91 }, { x: 5.821123, y: 6.83 } ]; const dataTwo = [ { x: 1.12, y: 5.7 }, { x: 7.5222, y: 4.91 }, { x: 1.55, y: 4.4 }, { x: 4.12, y: 6.911 }, { x: 6.15, y: 4.424 }, { x: 7.1, y: 5.421 }, { x: 6, y: 7.152 } ]; const dataThree = [ { x: 3.123, y: 3.17 }, { x: 2.422, y: 4.11453 }, { x: 1.1, y: 2 }, { x: 2.8235, y: 2.512 }, { x: 9.2, y: 7.411 }, { x: 8.3, y: 7.453 }, { x: 4.432, y: 3.811 } ]; const datasets = [ { label: 'Dataset #1', data: dataOne }, { label: 'Dataset #2', data: dataTwo }, { label: 'Dataset #3', data: dataThree } ]; const resetZoom = () => { chartRef.resetZoom(); }; const App = () => ( <> <MOScatterPlot ref={chartRef} yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" zoomable datasets={datasets} title="Scatter plot" subtitle="With point styling" ></MOScatterPlot> <MOButton onClick={resetZoom}></MOButton> </> );
Find all the zooming options in the plugin’s documentation.
Custom point radius and dates
The scatter plot points are displayed at 0.5 opacity by default, but enabling the boolean property
solidColors
will set the opacity to 1 for all points.
<mo-scatter-plot yAxisLabel="Sine" xAxisLabel="Date" title="Scatter plot" subtitle="With custom radii" pointRadius="1" id="radii" ></mo-scatter-plot> <script> const chart = document.querySelector('#radii'); const generateSineData = n => { const res = []; for (let i = 0; i < n; i++) { res.push({ x: new Date((i / 3) * 1000 * 60 * 60), y: Math.sin((((i / 3) * Math.PI) / 180) * 2 * Math.PI) }); } return res; }; const options = { scales: { x: { type: 'time', display: true, time: { unit: 'day' } } } }; const dateOptions = { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false }; const data = generateSineData(1000); const datasets = [{ label: 'Dataset #1', data: data, dateFormat: dateOptions }]; chart.options = options; chart.datasets = datasets; </script>
import { MOScatterPlot } from '@metsooutotec/modes-web-components/dist/react'; const generateSineData = n => { const res = []; for (let i = 0; i < n; i++) { res.push({ x: new Date((i / 3) * 1000 * 60 * 60), y: Math.sin((((i / 3) * Math.PI) / 180) * 2 * Math.PI) }); } return res; }; const options = { scales: { x: { type: 'time', display: true, time: { unit: 'day' } } } }; const dateOptions = { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false }; const data = generateSineData(1000); const datasets = [{ label: 'Dataset #1', data: data, dateFormat: dateOptions }]; const App = () => ( <> <MOScatterPlot yAxisLabel="Sine" xAxisLabel="Date" title="Scatter plot" subtitle="With custom radii" pointRadius="1" options={options} datasets={datasets} id="radii" ></MOScatterPlot> </> );
The date formatting on the tooltip can be customized by supplying a dateFormat
property for
the dataset. See the
Intl.DateTimeFormat MDX documentation
for more information about the possible options.
Solid colors and custom tick values
The scatter plot points are displayed at 0.5 opacity by default, but enabling the boolean property
solidColors
will set the opacity to 1 for all points.
<mo-scatter-plot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" title="Scatter plot" subtitle="With solid colors" solidColors id="solids" ></mo-scatter-plot> <script> const chart = document.querySelector('#solids'); const dataOne = [ { x: 1.44, y: 9.522 }, { x: 8.953, y: 5.912 }, { x: 0.533221, y: 5.53 }, { x: 3.5, y: 7.35 }, { x: 6.47, y: 4.98 }, { x: 7.723, y: 5.91 }, { x: 5.821123, y: 6.83 } ]; const dataTwo = [ { x: 1.12, y: 5.7 }, { x: 7.5222, y: 4.91 }, { x: 1.55, y: 4.4 }, { x: 4.12, y: 6.911 }, { x: 6.15, y: 4.424 }, { x: 7.1, y: 5.421 }, { x: 6, y: 7.152 } ]; const dataThree = [ { x: 3.123, y: 3.17 }, { x: 2.422, y: 4.11453 }, { x: 1.1, y: 2 }, { x: 2.8235, y: 2.512 }, { x: 9.2, y: 7.411 }, { x: 8.3, y: 7.453 }, { x: 4.432, y: 3.811 } ]; const datasets = [ { label: 'Dataset #1', data: dataOne }, { label: 'Dataset #2', data: dataTwo }, { label: 'Dataset #3', data: dataThree } ]; const options = { scales: { y: { ticks: { callback: function (value, index, ticks) { return value + ' mm'; } } }, x: { ticks: { callback: function (value, index, ticks) { return value + ' mm'; } } } } }; chart.options = options; chart.datasets = datasets; </script>
import { MOScatterPlot } from '@metsooutotec/modes-web-components/dist/react'; const dataOne = [ { x: 1.4, y: 9.5 }, { x: 8.9, y: 5.9 }, { x: 0.5, y: 5.5 }, { x: 3.5, y: 7.3 }, { x: 6.4, y: 4.9 }, { x: 7.723, y: 5.9 }, { x: 5.8, y: 6.8 } ]; const dataTwo = [ { x: 1, y: 5.7 }, { x: 7.5, y: 4.9 }, { x: 1.5, y: 4.4 }, { x: 4.1, y: 6.9 }, { x: 6.1, y: 4.4 }, { x: 7.1, y: 5.4 }, { x: 6.2, y: 7.1 } ]; const dataThree = [ { x: 3, y: 3.7 }, { x: 2.4, y: 4.1 }, { x: 1.1, y: 2.6 }, { x: 2.8, y: 2.5 }, { x: 9.2, y: 7.4 }, { x: 8.3, y: 7.4 }, { x: 4.4, y: 3.8 } ]; const datasets = [ { label: 'Dataset #1', data: dataOne }, { label: 'Dataset #2', data: dataTwo }, { label: 'Dataset #3', data: dataThree } ]; const App = () => ( <> <MOScatterPlot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" solidColors datasets={datasets} title="Scatter plot" subtitle="With solid colors" ></MOScatterPlot> </> );
Annotations
The charts in Modes UI can include annotations in the form of lines, boxes, and more. See the full documentation for the plugin here.
<mo-scatter-plot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" title="Scatter plot" subtitle="With annotations" id="annotation" ></mo-scatter-plot> <script> const chart = document.querySelector('#annotation'); const dataOne = [ { x: 1.4, y: 9.5 }, { x: 8.9, y: 5.9 }, { x: 0.5, y: 5.5 }, { x: 5.2, y: 7.3 }, { x: 6.4, y: 4.9 }, { x: 7.723, y: 5.9 }, { x: 5.8, y: 6.8 } ]; const dataTwo = [ { x: 1, y: 5.7 }, { x: 7.5, y: 4.9 }, { x: 1.5, y: 4.4 }, { x: 4.9, y: 6.9 }, { x: 6.1, y: 4.4 }, { x: 7.1, y: 5.4 }, { x: 6.2, y: 7.1 } ]; const dataThree = [ { x: 3, y: 3.7 }, { x: 2.4, y: 4.1 }, { x: 2.5, y: 2.6 }, { x: 2.8, y: 2.5 }, { x: 2.3, y: 7.4 }, { x: 3.2, y: 7.4 }, { x: 3.8, y: 3.8 } ]; const options = { scales: { x: { min: 0 }, y: { min: 0 } }, plugins: { annotation: { annotations: { ellipse1: { type: 'ellipse', xMin: 1.8, xMax: 4.1, yMin: 1.4, yMax: 8.6, backgroundColor: 'rgba(30, 130, 235, .05)' }, label1: { type: 'label', content: ['Highlighted data'], xValue: 3, yValue: 5.5, color: '#1e82eb', font: { size: 18 } } } } } }; const datasets = [ { label: 'Dataset #1', data: dataOne }, { label: 'Dataset #2', data: dataTwo }, { label: 'Dataset #3', data: dataThree } ]; chart.options = options; chart.datasets = datasets; </script>
import { MOScatterPlot } from '@metsooutotec/modes-web-components/dist/react'; const dataOne = [ { x: 1.4, y: 9.5 }, { x: 8.9, y: 5.9 }, { x: 0.5, y: 5.5 }, { x: 5.2, y: 7.3 }, { x: 6.4, y: 4.9 }, { x: 7.723, y: 5.9 }, { x: 5.8, y: 6.8 } ]; const dataTwo = [ { x: 1, y: 5.7 }, { x: 7.5, y: 4.9 }, { x: 1.5, y: 4.4 }, { x: 4.9, y: 6.9 }, { x: 6.1, y: 4.4 }, { x: 7.1, y: 5.4 }, { x: 6.2, y: 7.1 } ]; const dataThree = [ { x: 3, y: 3.7 }, { x: 2.4, y: 4.1 }, { x: 2.5, y: 2.6 }, { x: 2.8, y: 2.5 }, { x: 2.3, y: 7.4 }, { x: 3.2, y: 7.4 }, { x: 3.8, y: 3.8 } ]; const options = { scales: { x: { min: 0 }, y: { min: 0 } }, plugins: { annotation: { annotations: { ellipse1: { type: 'ellipse', xMin: 1.8, xMax: 4.1, yMin: 1.4, yMax: 8.6, backgroundColor: 'rgba(30, 130, 235, .05)' }, label1: { type: 'label', content: ['Highlighted data'], xValue: 3, yValue: 5.5, color: '#1e82eb', font: { size: 18 } } } } } }; const datasets = [ { label: 'Dataset #1', data: dataOne }, { label: 'Dataset #2', data: dataTwo }, { label: 'Dataset #3', data: dataThree } ]; const App = () => ( <> <MOScatterPlot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" options={options} datasets={datasets} title="Scatter plot" subtitle="With annotations" ></MOScatterPlot> </> );
Trendline
The scatter plot can automatically generate a trendline (based on linear regression) for each dataset in the
chart. To do this, simply enable the trendlines
property.
<mo-scatter-plot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" title="Scatter plot" subtitle="With trendlines" id="trend-line" trendlines ></mo-scatter-plot> <script> const chart = document.querySelector('#trend-line'); const data = [ { x: 1.2, y: 2.5 }, { x: 2.1, y: 3.1 }, { x: 2.4, y: 3.8 }, { x: 2.8, y: 4.5 }, { x: 3.8, y: 5.0 }, { x: 4.4, y: 6.3 }, { x: 4.9, y: 7.2 }, { x: 5.9, y: 7.4 }, { x: 6.4, y: 7.8 } ]; const dataTwo = [ { x: 1.2, y: 7.8 }, { x: 1.9, y: 7.4 }, { x: 3, y: 6.7 }, { x: 3.4, y: 6.6 }, { x: 3.9, y: 5.6 }, { x: 4.5, y: 5.9 }, { x: 5.3, y: 5.2 }, { x: 5.9, y: 4.2 }, { x: 6.7, y: 3.2 } ]; const options = { scales: { x: { min: 0 }, y: { min: 0 } } }; const datasets = [ { label: 'Dataset #1', data: data }, { label: 'Dataset #2', data: dataTwo } ]; chart.options = options; chart.datasets = datasets; </script>
import { MOScatterPlot } from '@metsooutotec/modes-web-components/dist/react'; const data = [ { x: 1.2, y: 2.5 }, { x: 2.1, y: 3.1 }, { x: 2.4, y: 3.8 }, { x: 2.8, y: 4.5 }, { x: 3.8, y: 5.0 }, { x: 4.4, y: 6.3 }, { x: 4.9, y: 7.2 }, { x: 5.9, y: 7.4 }, { x: 6.4, y: 7.8 } ]; const dataTwo = [ { x: 1.2, y: 7.8 }, { x: 1.9, y: 7.4 }, { x: 3, y: 6.7 }, { x: 3.4, y: 6.6 }, { x: 3.9, y: 5.6 }, { x: 4.5, y: 5.9 }, { x: 5.3, y: 5.2 }, { x: 5.9, y: 4.2 }, { x: 6.7, y: 3.2 } ]; const options = { scales: { x: { min: 0 }, y: { min: 0 } } }; const datasets = [ { label: 'Dataset #1', data: data }, { label: 'Dataset #2', data: dataTwo } ]; const App = () => ( <> <MOScatterPlot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" trendlines options={options} datasets={datasets} title="Scatter plot" subtitle="With trendlines" ></MOScatterPlot> </> );
For the trendline to be calculated correctly, data must be given as an array of objects that have an
x
and a y
value, i.e., a
ScatterDataPoint.
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-scatter-plot legendPosition="right" legendAlignment="start" subtitle="Custom legend positioning" title="Scatter plot" id="legend-pos" ></mo-scatter-plot> <script> const chart = document.querySelector('#legend-pos'); const posSelect = document.querySelector('#pos-select'); const alignSelect = document.querySelector('#align-select'); const data = [ { x: 1.2, y: 2.5 }, { x: 2.1, y: 3.1 }, { x: 2.4, y: 3.8 }, { x: 2.8, y: 4.5 }, { x: 3.8, y: 5.0 }, { x: 4.4, y: 6.3 }, { x: 4.9, y: 7.2 }, { x: 5.9, y: 7.4 }, { x: 6.4, y: 7.8 } ]; const dataTwo = [ { x: 1.2, y: 7.8 }, { x: 1.9, y: 7.4 }, { x: 3, y: 6.7 }, { x: 3.4, y: 6.6 }, { x: 3.9, y: 5.6 }, { x: 4.5, y: 5.9 }, { x: 5.3, y: 5.2 }, { x: 5.9, y: 4.2 }, { x: 6.7, y: 3.2 } ]; const options = { scales: { x: { min: 0 }, y: { min: 0 } } }; const datasets = [ { label: 'Dataset #1', data: data }, { label: 'Dataset #2', data: dataTwo } ]; chart.options = options; chart.datasets = datasets; 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; }); </script>
import { MOLineChart, MODivider, MOSelect, MOOption } from '@metsooutotec/modes-web-components/dist/react'; const scatterPlotRef = useRef(null); const data = [ { x: 1.2, y: 2.5 }, { x: 2.1, y: 3.1 }, { x: 2.4, y: 3.8 }, { x: 2.8, y: 4.5 }, { x: 3.8, y: 5.0 }, { x: 4.4, y: 6.3 }, { x: 4.9, y: 7.2 }, { x: 5.9, y: 7.4 }, { x: 6.4, y: 7.8 } ]; const dataTwo = [ { x: 1.2, y: 7.8 }, { x: 1.9, y: 7.4 }, { x: 3, y: 6.7 }, { x: 3.4, y: 6.6 }, { x: 3.9, y: 5.6 }, { x: 4.5, y: 5.9 }, { x: 5.3, y: 5.2 }, { x: 5.9, y: 4.2 }, { x: 6.7, y: 3.2 } ]; const options = { scales: { x: { min: 0 }, y: { min: 0 } } }; const datasets = [ { label: 'Dataset #1', data: data }, { label: 'Dataset #2', data: dataTwo } ]; const updatePos = e => { scatterPlotRef.legendPosition = e.target.value; }; const updateAlign = e => { scatterPlotRef.legendAlignment = e.target.value; }; 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} options={options} legendPosition="right" legendAlignment="start" subtitle="Custom legend positioning" title="Scatter plot" ref={scatterPlotRef} ></MOLineChart> </> );
Bubble chart
The scatter plot can accept a third data point, that specifies the size of each data point. For this, the
chart must have the property bubble
enabled, and the size must be given as a radius using the
key r
, as shown in the example. We recommend bubbles are sized systematically, where the steps
are r: 6
(default), r: 10
, and r: 14
. This will results in points
with width and height of 12px, 20px, and 24px respectively.
Quantity
0–10
10–50
50–100
<div class="chartAndExtraLegendContainer"> <mo-scatter-plot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" zAxisLabel="Quantity" zAxisUnit="pcs." title="Scatter plot" subtitle="With an extra legend" id="third-var" bubble class="flex-grow" ></mo-scatter-plot> <div class="extraLegend"> <p>Quantity</p> <div class="innerLegendContainer"> <canvas class="legendCanvas" id="circle-1"></canvas> <p class="numberLabel">0-10</p> </div> <div class="innerLegendContainer"> <canvas class="legendCanvas" id="circle-2"></canvas> <p class="numberLabel">10-50</p> </div> <div class="innerLegendContainer"> <canvas class="legendCanvas" id="circle-3"></canvas> <p class="numberLabel">50-100</p> </div> </div> </div> <script> const chart = document.querySelector('#third-var'); const dataOne = [ { x: 6, y: 6.8, z: 92, r: 14 }, { x: 8.9, y: 5.9, z: 30, r: 10 }, { x: 5.8, y: 4.2, z: 26, r: 10 }, { x: 3.5, y: 7.3, z: 4, r: 6 }, { x: 6.4, y: 4.9, z: 74, r: 14 }, { x: 7.243, y: 6.2, z: 9, r: 6 }, { x: 5.9, y: 7.0, z: 55, r: 14 } ]; for (var i = 0; i < 3; i++) { const id = `circle-${i + 1}`; const canvas = document.getElementById(id); const context = canvas.getContext('2d'); canvas.width = 32; canvas.height = 32; context.rect(0, 0, 32, 32); context.fillStyle = '#E6E6E6'; context.fill(); const centerX = canvas.width / 2; const centerY = canvas.height / 2; const radius = 6 + i * 4; context.beginPath(); context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); context.fillStyle = 'rgba(103, 48, 191, 0.5)'; context.fill(); context.lineWidth = 1; context.strokeStyle = 'rgba(103, 48, 191, 1)'; context.stroke(); } const datasets = [{ label: 'Dataset #1', data: dataOne }]; chart.datasets = datasets; </script> <style> .chartAndExtraLegendContainer { display: flex; flex-direction: row; justify-content: space-between; font-family: 'GT-Eesti'; } .flex-grow { flex-grow: 1; } .extraLegend { display: flex; flex-direction: column; gap: 4px; } .innerLegendContainer { display: flex; font-size: 14px; align-items: center; gap: 4px; } .numberLabel { margin: 0; font-size: 12px; } .legendCanvas { width: 32px; height: 32px; } </style>
import { MOScatterPlot } from '@metsooutotec/modes-web-components/dist/react'; const css = ` .chartAndExtraLegendContainer { display: flex; flex-direction: row; justify-content: space-between; font-family: 'GT-Eesti'; } .flex-grow { flex-grow: 1; } .extraLegend { display: flex; flex-direction: column; gap: 4px; } .innerLegendContainer { display: flex; font-size: 14px; align-items: center; gap: 4px; } .numberLabel { margin: 0; font-size: 12px; } .legendCanvas { width: 32px; height: 32px; } `; const dataOne = [ { x: 6, y: 6.8, z: 92, r: 14 }, { x: 8.9, y: 5.9, z: 30, r: 10 }, { x: 5.8, y: 4.2, z: 26, r: 10 }, { x: 3.5, y: 7.3, z: 4, r: 6 }, { x: 6.4, y: 4.9, z: 74, r: 14 }, { x: 7.243, y: 6.2, z: 9, r: 6 }, { x: 5.9, y: 7.0, z: 55, r: 14 } ]; for (var i = 0; i < 3; i++) { const id = `circle-${i + 1}`; const canvas = document.getElementById(id); const context = canvas.getContext('2d'); canvas.width = 32; canvas.height = 32; context.rect(0, 0, 32, 32); context.fillStyle = '#E6E6E6'; context.fill(); const centerX = canvas.width / 2; const centerY = canvas.height / 2; const radius = 6 + i * 4; context.beginPath(); context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); context.fillStyle = 'rgba(103, 48, 191, 0.5)'; context.fill(); context.lineWidth = 1; context.strokeStyle = 'rgba(103, 48, 191, 1)'; context.stroke(); } const datasets = [{ label: 'Dataset #1', data: dataOne }]; const App = () => ( <> <div class="chartAndExtraLegendContainer"> <MOScatterPlot yAxisLabel="Vertical displacement" xAxisLabel="Horizontal displacement" yAxisUnit="mm" xAxisUnit="mm" zAxisLabel="Quantity" zAxisUnit="pcs." title="Scatter plot" subtitle="With an extra legend" datasets={datasets} bubble class="flex-grow" ></MOScatterPlot> <div class="extraLegend"> <p>Quantity</p> <div class="innerLegendContainer"> <canvas class="legendCanvas" id="circle-1"></canvas> <p class="numberLabel">0-10</p> </div> <div class="innerLegendContainer"> <canvas class="legendCanvas" id="circle-2"></canvas> <p class="numberLabel">10-50</p> </div> <div class="innerLegendContainer"> <canvas class="legendCanvas" id="circle-3"></canvas> <p class="numberLabel">50-100</p> </div> </div> </div> <style>{css}</style> </> );
The extra legend on the right here is custom made for this example, and is not part of the component itself. Check the source code to see how to replicate it.
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/scatter-plot/scatter-plot.js';
To import this component as a React component:
import MOScatterPlot from '@metsooutotec/modes-web-components/dist/react/scatter-plot/';
To import this component using a script tag:
<script type="module" src="https://modes-web.metso.com/dist/components/cdn/components/scatter-plot/scatter-plot.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
|
'scatter'
|
|
chart
|
Reference to the chart itself. |
Chart
|
- | |
datasets
|
Datasets for the chart. |
|
ChartDataset[]
|
[]
|
xAxisLabel
x-axis-label
|
Label to show on the x-axis. |
string
|
''
|
|
yAxisLabel
y-axis-label
|
Label to show on the y-axis. |
string
|
''
|
|
zAxisLabel
z-axis-label
|
Label to show on the y-axis. |
string
|
''
|
|
xAxisUnit
x-axis-unit
|
Unit of values on the x-axis. |
string
|
''
|
|
yAxisUnit
y-axis-unit
|
Unit of values on the y-axis. |
string
|
''
|
|
zAxisUnit
z-axis-unit
|
Unit of values on the z-axis. |
string
|
''
|
|
title
|
Title to be shown above the chart. |
string
|
''
|
|
subtitle
|
Subtitle to be shown above the chart, but below title. |
string
|
''
|
|
legendAlignment
legend-alignment
|
Alignment of the legends. |
'start' | 'end'
|
'start'
|
|
legendPosition
legend-position
|
Position of the legends. |
'bottom' | 'right' | 'left' | 'top'
|
'bottom'
|
|
customPlugins
custom-plugins
|
Use this property to add custom plugins to the created chart.js instance |
Plugin[]
|
[]
|
|
hideLegends
hide-legends
|
Hide the legends. |
|
boolean
|
false
|
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' } }
|
styledPoints
styled-points
|
Style the points of different data sets differently. |
|
boolean
|
false
|
trendlines
|
Automatically draw trend lines (linear regression) for each dataset. |
|
boolean
|
false
|
zoomable
|
Enables zooming on the chart. |
|
boolean
|
false
|
bubble
|
Changes chart to a bubble chart. |
|
boolean
|
false
|
solidColors
solid-colors
|
Data points are drawn in solid colors (opacity 1), they have opacity 0.5 by default. |
|
boolean
|
false
|
pointRadius
|
The radius for each point of data in the plot. Defaults to 6. |
|
number
|
6
|
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.