Polar 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 Polar 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 pieCategories = [
  "Product A",
  "Product B",
  "Product C",
  "Product D",
  "Product E",
];

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

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

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 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 generateNormalizedData = (data: number[]) => {
  const total = data.reduce((sum, value) => sum + value, 0);
  return data.map((value) => Math.round((value / total) * 100));
};

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

export const generateRandomNegativeData = (
  count: number,
  max: number,
  min: number
) => {
  return Array.from({ length: count }, () => {
    const isNegative = Math.random() > 0.5;
    const value = Math.floor(Math.random() * (max - min + 1) + min);
    return isNegative ? -value : value;
  });
};

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 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 Polar Chart

Live Preview
Open in
chart.js

Label Polar Chart

Live Preview
Open in

Normalized Polar Chart

Live Preview
Open in

Polar Radar Chart

Live Preview
Open in
JavaScript
React
Node.js
Python
Design
Communication

Line Polar Chart

Live Preview
Open in

Wind Polar Chart

Live Preview
Open in
Wind Speed by Direction
0-5 mph
5-10 mph
10-15 mph
15-20 mph
20+ mph

Rose Polar Chart

Live Preview
Open in
Rose Pattern Visualization

WebGL Polar Chart

Live Preview
Open in
High-Performance Visualization
16 data points

Stacked Polar Chart

Live Preview
Open in
Multi-Layer Data Visualization
Layer 1
Base values
Layer 2
Additional data
Layer 3
Top layer

Interactive Chart

Live Preview
Open in
💡 Click segments to interact

On this page