Skip to content

ExamplesTrends & comparison

Scatter

Each point is an [x, y] pair. When both positions matter, turn on the x-gridlines too (xAxis: { grid: true } — the y-grid is already on by default).

ts
import { createChart } from '@chartcraft/core';

const chart = createChart(document.querySelector<HTMLElement>('#chart')!, {
  type: 'scatter',
  title: 'Deal size vs. sales cycle',
  subtitle: 'Closed-won deals, trailing 12 months',
  data: {
    series: [
      {
        id: 'new-business',
        name: 'New business',
        data: [
          [14, 18], [22, 25], [31, 34], [45, 41], [52, 46], [61, 58],
          [38, 39], [27, 30], [74, 66], [89, 74], [56, 52], [42, 47],
          [19, 24], [68, 61], [95, 82], [33, 31],
        ],
      },
      {
        id: 'expansion',
        name: 'Expansion',
        data: [
          [12, 9], [18, 14], [26, 17], [35, 22], [48, 28], [57, 31],
          [24, 16], [41, 25], [66, 35], [78, 41], [30, 19], [51, 27],
        ],
      },
    ],
  },
  xAxis: { label: 'Deal size (USD, thousands)', grid: true, min: 0 },
  yAxis: { label: 'Sales cycle (days)', min: 0 },
  a11y: {
    description:
      'Larger deals take longer to close; expansion deals close roughly twice as fast as new business at every deal size.',
  },
});
vue
<script setup lang="ts">
import { ScatterChart } from '@chartcraft/vue';
import type { ChartSpec } from '@chartcraft/vue';

const options: ChartSpec = {
  title: 'Deal size vs. sales cycle',
  subtitle: 'Closed-won deals, trailing 12 months',
  data: {
    series: [
      {
        id: 'new-business',
        name: 'New business',
        data: [
          [14, 18], [22, 25], [31, 34], [45, 41], [52, 46], [61, 58],
          [38, 39], [27, 30], [74, 66], [89, 74], [56, 52], [42, 47],
          [19, 24], [68, 61], [95, 82], [33, 31],
        ],
      },
      {
        id: 'expansion',
        name: 'Expansion',
        data: [
          [12, 9], [18, 14], [26, 17], [35, 22], [48, 28], [57, 31],
          [24, 16], [41, 25], [66, 35], [78, 41], [30, 19], [51, 27],
        ],
      },
    ],
  },
  xAxis: { label: 'Deal size (USD, thousands)', grid: true, min: 0 },
  yAxis: { label: 'Sales cycle (days)', min: 0 },
  a11y: {
    description:
      'Larger deals take longer to close; expansion deals close roughly twice as fast as new business at every deal size.',
  },
};
</script>

<template>
  <ScatterChart :options="options" style="height: 340px" />
</template>

Scatter tooltips are per-mark by default, and hit targets use nearest-point matching within 24px — nobody has to land a pointer on an 8px dot. Very large point clouds downsample automatically past 5,000 points per series; see the large-data showcase.