Lightweight Performant Canvas Charting Library – Chartie

Category: Chart & Graph , Javascript | July 19, 2025
Authorddoemonn
Last UpdateJuly 19, 2025
LicenseMIT
Tags
Views37 views
Lightweight Performant Canvas Charting Library – Chartie

Chartie is a lightweight canvas-based charting library that enables you to create interactive data visualizations for modern web apps where performance and bundle size matter.

Features:

  • Six chart types: Bar, line, pie, doughnut, area, and scatter plots
  • Ultra-lightweight: Complete library under 10kb bundled
  • Canvas-based rendering: Direct GPU acceleration with pure Canvas API
  • Smooth animations: Built-in easing functions with configurable durations
  • Responsive design: Automatic scaling and retina display support
  • TypeScript support: Full type definitions included
  • Zero dependencies: No external libraries required

How to use it:

1. Install Chartie via npm.

npm install chartie

2. Place a canvas element in your HTML with a unique ID.

<canvas id="example"></canvas>

3. Import Chartie and create a new instance. The constructor takes the canvas element’s ID and a configuration object.

import { Chartie } from 'chartie';
// Define the chart's data and options
const config = {
  type: 'bar',
  data: {
    labels: ['Jan', 'Feb', 'Mar'],
    datasets: [{
      label: 'Sales',
      data: [12, 19, 3],
      backgroundColor: '#3b82f6'
    }]
  }
};
// Create the chart
const chart = new Chartie('example', config);

4. Chart types and configurations:

// bar chart
const config = {
  type: 'bar',
  data: {
    labels: ['Jan', 'Feb', 'Mar'],
    datasets: [{
      label: 'Sales',
      data: [12, 19, 3],
      backgroundColor: '#3b82f6'
    }]
  }
};
// line chart
const config = {
  "type": "line",
  "data": {
    "labels": [
      "Week 1",
      "Week 2",
      "Week 3",
      "Week 4",
      "Week 5",
      "Week 6"
    ],
    "datasets": [
      {
        "label": "Active Users",
        "data": [
          1200,
          1900,
          3000,
          5000,
          2000,
          3000
        ],
        "borderColor": "#10b981",
        "backgroundColor": "rgba(16, 185, 129, 0.1)",
        "borderWidth": 3,
        "fill": false,
        "tension": 0.4
      },
      {
        "label": "New Signups",
        "data": [
          800,
          1200,
          2000,
          3500,
          1500,
          2200
        ],
        "borderColor": "#f59e0b",
        "backgroundColor": "rgba(245, 158, 11, 0.1)",
        "borderWidth": 3,
        "fill": false,
        "tension": 0.4
      }
    ]
  },
  "options": {
    "responsive": true,
    "animation": {
      "duration": 1000,
      "easing": "easeInOut"
    }
  }
}
// pie chart
const config = {
  "type": "pie",
  "data": {
    "labels": [
      "React",
      "Vue",
      "Angular",
      "Svelte",
      "Next.js"
    ],
    "datasets": [
      {
        "data": [
          35,
          25,
          20,
          12,
          8
        ],
        "backgroundColor": [
          "#6366f1",
          "#10b981",
          "#f59e0b",
          "#ef4444",
          "#8b5cf6"
        ]
      }
    ]
  },
  "options": {
    "animation": {
      "duration": 1500,
      "easing": "easeInOut"
    }
  }
}
// donut chart
const config = {
  "type": "doughnut",
  "data": {
    "labels": [
      "Desktop",
      "Mobile",
      "Tablet"
    ],
    "datasets": [
      {
        "data": [
          60,
          35,
          5
        ],
        "backgroundColor": [
          "#06b6d4",
          "#10b981",
          "#f59e0b"
        ]
      }
    ]
  },
  "options": {
    "animation": {
      "duration": 1300,
      "easing": "easeInOut"
    }
  }
}
// area chart
const config = {
  "type": "area",
  "data": {
    "labels": [
      "Q1",
      "Q2",
      "Q3",
      "Q4"
    ],
    "datasets": [
      {
        "label": "Sales Growth",
        "data": [
          100,
          150,
          300,
          250
        ],
        "borderColor": "#8b5cf6",
        "backgroundColor": "rgba(139, 92, 246, 0.2)",
        "borderWidth": 2,
        "tension": 0.3
      }
    ]
  },
  "options": {
    "animation": {
      "duration": 1100,
      "easing": "easeInOut"
    }
  }
}
// scatter chart
const config = {
  "type": "scatter",
  "data": {
    "datasets": [
      {
        "label": "Dataset 1",
        "data": [
          {
            "x": 10,
            "y": 20
          },
          {
            "x": 15,
            "y": 25
          },
          {
            "x": 20,
            "y": 22
          },
          {
            "x": 25,
            "y": 28
          },
          {
            "x": 30,
            "y": 35
          },
          {
            "x": 35,
            "y": 32
          }
        ],
        "backgroundColor": "#ef4444"
      },
      {
        "label": "Dataset 2",
        "data": [
          {
            "x": 12,
            "y": 15
          },
          {
            "x": 18,
            "y": 20
          },
          {
            "x": 22,
            "y": 18
          },
          {
            "x": 28,
            "y": 25
          },
          {
            "x": 32,
            "y": 30
          },
          {
            "x": 38,
            "y": 28
          }
        ],
        "backgroundColor": "#06b6d4"
      }
    ]
  },
  "options": {
    "animation": {
      "duration": 900,
      "easing": "easeInOut"
    }
  }
}

5. React integration. You’ll want to use a ref to access the canvas element and useEffect to manage the chart’s lifecycle. This is important because you need to clean up the chart instance when the component unmounts.

import { useEffect, useRef } from 'react';
import { Chartie } from 'chartie';
function LineChartComponent() {
  const canvasRef = useRef(null);
  useEffect(() => {
    // canvasRef.current is the <canvas> element
    const chart = new Chartie(canvasRef.current, {
      type: 'line',
      data: {
        labels: ['Mon', 'Tue', 'Wed', 'Thu'],
        datasets: [{
          label: 'Revenue',
          data: [65, 59, 80, 81],
          borderColor: '#ef4444',
          tension: 0.4 // Creates a nice curve
        }]
      }
    });
    // Cleanup function to run when the component unmounts
    return () => chart.destroy();
  }, []); // Empty dependency array runs this effect once
  return <canvas ref={canvasRef}></canvas>;
}

6. All possible configuration options:

// Core chart types
export type ChartType = 'bar' | 'line' | 'pie' | 'doughnut' | 'area' | 'scatter';
// Color types
export type Color = string | CanvasGradient | CanvasPattern;
// Data point types
export interface DataPoint {
  x: number;
  y: number;
  label?: string;
}
export interface Dataset {
  label?: string;
  data: number[] | DataPoint[];
  backgroundColor?: Color | Color[];
  borderColor?: Color;
  borderWidth?: number;
  fill?: boolean;
  tension?: number; // for line charts
}
// Chart configuration
export interface ChartConfig {
  type: ChartType;
  data: {
    labels?: string[];
    datasets: Dataset[];
  };
  options?: ChartOptions;
}
export interface ChartOptions {
  responsive?: boolean;
  maintainAspectRatio?: boolean;
  backgroundColor?: Color;
  
  // Animation
  animation?: {
    duration?: number;
    easing?: 'linear' | 'easeInOut' | 'easeIn' | 'easeOut';
  };
  
  // Scales (for bar, line, area, scatter charts)
  scales?: {
    x?: AxisConfig;
    y?: AxisConfig;
  };
  
  // Legend
  legend?: {
    display?: boolean;
    position?: 'top' | 'bottom' | 'left' | 'right';
    labels?: {
      color?: Color;
      font?: {
        size?: number;
        family?: string;
      };
    };
  };
  
  // Tooltip
  tooltip?: {
    enabled?: boolean;
    backgroundColor?: Color;
    titleColor?: Color;
    bodyColor?: Color;
    borderColor?: Color;
    borderWidth?: number;
  };
  
  // Padding
  padding?: {
    top?: number;
    right?: number;
    bottom?: number;
    left?: number;
  };
}
export interface AxisConfig {
  display?: boolean;
  min?: number;
  max?: number;
  grid?: {
    display?: boolean;
    color?: Color;
    lineWidth?: number;
  };
  ticks?: {
    display?: boolean;
    color?: Color;
    font?: {
      size?: number;
      family?: string;
    };
  };
}
// Internal chart bounds and dimensions
export interface ChartBounds {
  x: number;
  y: number;
  width: number;
  height: number;
}
// Animation frame interface
export interface AnimationFrame {
  progress: number;
  currentValues: Record<string, number>;
}

You Might Be Interested In:


Leave a Reply