Skip to main content
Default Gray Amethyst

Scatter Plot

<mo-scatter-plot> | MOScatterPlot
Since 1.5 stable

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>
);

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.

Reset zoom
<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>
  </>
);

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>
  </>
);

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>
  </>
);

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.

Top Left Bottom Right Start End
<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>
  </>
);

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.

Bundler React Script

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.