Scatter Chart

Beautiful charts. Built using chartjs and react-chartjs-2. Copy and paste into your apps or run the command into your CLI.


1. Install utilities

You need to install some necessary packages to use the below Scatter Charts. Please run the command into your terminal.

bun add chart.js react-chartjs-2

2. Setup files

Create a file named as chart-utils.ts inside your lib folder and paste the code.

"use client";

import { useTheme } from "next-themes";
import { useEffect, useState } from "react";

export type ChartColors = {
  primary: string;
  secondary: string;
  tertiary: string;
  quaternary: string;
  quinary: string;
  senary: string;
  background: string;
  grid: string;
  text: string;
  muted: string;
};

export function useChartColors(): ChartColors {
  const { theme } = useTheme();
  const [colors, setColors] = useState<ChartColors>({
    primary: "rgb(99, 102, 241)",
    secondary: "rgb(168, 85, 247)",
    tertiary: "rgb(249, 115, 22)",
    quaternary: "rgb(34, 197, 94)",
    quinary: "rgb(239, 68, 68)",
    senary: "rgb(6, 182, 212)",
    background: "rgb(255, 255, 255)",
    grid: "rgb(243, 244, 246)",
    text: "rgb(17, 24, 39)",
    muted: "rgb(156, 163, 175)",
  });

  useEffect(() => {
    if (theme === "dark") {
      setColors({
        primary: "rgb(129, 140, 248)",
        secondary: "rgb(192, 132, 252)",
        tertiary: "rgb(251, 146, 60)",
        quaternary: "rgb(74, 222, 128)",
        quinary: "rgb(248, 113, 113)",
        senary: "rgb(34, 211, 238)",
        background: "rgb(17, 24, 39)",
        grid: "rgb(55, 65, 81)",
        text: "rgb(243, 244, 246)",
        muted: "rgb(107, 114, 128)",
      });
    } else {
      setColors({
        primary: "rgb(99, 102, 241)",
        secondary: "rgb(168, 85, 247)",
        tertiary: "rgb(249, 115, 22)",
        quaternary: "rgb(34, 197, 94)",
        quinary: "rgb(239, 68, 68)",
        senary: "rgb(6, 182, 212)",
        background: "rgb(255, 255, 255)",
        grid: "rgb(243, 244, 246)",
        text: "rgb(17, 24, 39)",
        muted: "rgb(156, 163, 175)",
      });
    }
  }, [theme]);

  return colors;
}

export const months = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December",
];

export const categories = [
  "Desktop",
  "Mobile",
  "Tablet",
  "Smart TV",
  "Wearables",
  "Other",
];

export const radarLabels = [
  "Speed",
  "Reliability",
  "Comfort",
  "Safety",
  "Efficiency",
  "Design",
];

export const skillLabels = [
  "JavaScript",
  "React",
  "Node.js",
  "Python",
  "Design",
  "Communication",
];

// Add these new utilities for polar area charts
export const polarCategories = [
  "North",
  "Northeast",
  "East",
  "Southeast",
  "South",
  "Southwest",
  "West",
  "Northwest",
];

export const windDirections = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];

export const generatePolarData = (count: number, max = 100, min = 10) => {
  return Array.from({ length: count }, () =>
    Math.floor(Math.random() * (max - min + 1) + min)
  );
};

export const generateWindData = (count: number, max = 25, min = 5) => {
  return Array.from({ length: count }, () =>
    Math.floor(Math.random() * (max - min + 1) + min)
  );
};

export const generateScatterPolarData = (count: number) => {
  return Array.from({ length: count }, (_, i) => ({
    x: i * (360 / count), // angle in degrees
    y: Math.floor(Math.random() * 100 + 10), // radius
  }));
};

export const generateNormalizedData = (data: number[]) => {
  const total = data.reduce((sum, value) => sum + value, 0);
  return data.map((value) => Math.round((value / total) * 100));
};

export const generateRandomData = (count: number, max: number, min = 0) => {
  return Array.from({ length: count }, () =>
    Math.floor(Math.random() * (max - min + 1) + min)
  );
};

export const generateRadarData = (count: number, max = 100, min = 20) => {
  return Array.from({ length: count }, () =>
    Math.floor(Math.random() * (max - min + 1) + min)
  );
};

export const generateProgressValue = (max = 100, min = 10) => {
  return Math.floor(Math.random() * (max - min + 1) + min);
};

export const generatePieColors = (colors: ChartColors) => [
  colors.primary,
  colors.secondary,
  colors.tertiary,
  colors.quaternary,
  colors.quinary,
  colors.senary,
];

export const createGradient = (
  ctx: CanvasRenderingContext2D,
  color: string,
  opacity = 0.2
) => {
  const gradient = ctx.createLinearGradient(0, 0, 0, 400);
  gradient.addColorStop(
    0,
    color.replace("rgb", "rgba").replace(")", `, ${opacity})`)
  );
  gradient.addColorStop(1, color.replace("rgb", "rgba").replace(")", ", 0)"));
  return gradient;
};

// Add these new utilities for scatter charts
export const generateScatterData = (
  count: number,
  xMax = 100,
  yMax = 100,
  xMin = 0,
  yMin = 0
) => {
  return Array.from({ length: count }, () => ({
    x: Math.floor(Math.random() * (xMax - xMin + 1) + xMin),
    y: Math.floor(Math.random() * (yMax - yMin + 1) + yMin),
  }));
};

export const generatePositiveScatterData = (
  count: number,
  xMax = 100,
  yMax = 100
) => {
  return Array.from({ length: count }, () => ({
    x: Math.floor(Math.random() * xMax + 1),
    y: Math.floor(Math.random() * yMax + 1),
  }));
};

export const generateNegativeScatterData = (
  count: number,
  xMax = 50,
  yMax = 50
) => {
  return Array.from({ length: count }, () => ({
    x: Math.floor(Math.random() * xMax - xMax / 2),
    y: Math.floor(Math.random() * yMax - yMax / 2),
  }));
};

export const generateCorrelatedData = (count: number, correlation = 0.8) => {
  return Array.from({ length: count }, () => {
    const x = Math.random() * 100;
    const y =
      correlation * x +
      (1 - correlation) * Math.random() * 100 +
      Math.random() * 20 -
      10;
    return { x: Math.round(x), y: Math.round(Math.max(0, Math.min(100, y))) };
  });
};

export const generate3DScatterData = (count: number) => {
  return Array.from({ length: count }, () => ({
    x: Math.floor(Math.random() * 100),
    y: Math.floor(Math.random() * 100),
    z: Math.floor(Math.random() * 100),
  }));
};

export const generateMatrixData = (rows: number, cols: number) => {
  const data = [];
  for (let i = 0; i < rows; i++) {
    for (let j = 0; j < cols; j++) {
      data.push({
        x: j,
        y: i,
        value: Math.floor(Math.random() * 100),
      });
    }
  }
  return data;
};

export const generateDensityData = (count: number) => {
  const clusters = [
    { centerX: 25, centerY: 25, spread: 10 },
    { centerX: 75, centerY: 75, spread: 15 },
    { centerX: 50, centerY: 20, spread: 8 },
  ];

  return Array.from({ length: count }, () => {
    const cluster = clusters[Math.floor(Math.random() * clusters.length)];
    const angle = Math.random() * 2 * Math.PI;
    const radius = Math.random() * cluster.spread;

    return {
      x: Math.round(cluster.centerX + radius * Math.cos(angle)),
      y: Math.round(cluster.centerY + radius * Math.sin(angle)),
    };
  });
};

export const scatterCategories = [
  "Category A",
  "Category B",
  "Category C",
  "Category D",
];

export const generateCategoricalScatterData = (categories: string[]) => {
  return categories.map((category, categoryIndex) => ({
    label: category,
    data: Array.from({ length: 15 + Math.floor(Math.random() * 10) }, () => ({
      x: Math.floor(Math.random() * 100),
      y: Math.floor(Math.random() * 100),
      category: categoryIndex,
    })),
  }));
};

Thats it. You are ready to go!


Basic Scatter

Live Preview
Open in

Label Scatter

Live Preview
Open in

Matrix Scatter

Live Preview
Open in
8x8 Matrix Visualization
0-20
21-40
41-60
61-80
81-100

3D Scatter

Live Preview
Open in
3D Data Visualization
Z Dimension Legend:
Low Z (0-25)
Medium Z (26-75)
High Z (76-100)
Point size and color intensity represent the Z dimension value

Line Scatter

Live Preview
Open in
Correlation Analysis
Slope
0.736
Intercept
11.92
0.926

Grouped Scatter

Live Preview
Open in
Multi-Category Analysis
Category A
18 points
Category B
17 points
Category C
16 points
Category D
17 points

Density Scatter

Live Preview
Open in
Density & Clustering Analysis
Total Points
150
Density Centers
44
Max Density
16

Interactive Scatter

Live Preview
Open in
Selected: 0 / 50 points
Total Points
50
Selected
0
Zoom Level
1.0x
Point Size
5px
💡 Click points to select, use controls to interact

On this page