Skip to content

Lilanga/handwritten-graph-ts

Repository files navigation

Handwritten Graph Library (TypeScript)

A modern TypeScript library for creating hand-drawn style charts inspired by comics and sketches. Built with D3.js and designed with type safety and excellent developer experience in mind.

Documentation

Example

Here’s some example of a graph generated with this library:

Bar charts

Example Handwritten Graph

Pie charts

Example Handwritten Graph

Donut charts

Example Handwritten Graph

Complete API Documentation

📚 Live Demo | 📖 Quick Start

Features

  • 🖌️ Real watercolor washes - Per-shape layered pigment with edge darkening, interior pooling, and feathered edges (fillStyle: 'watercolor')
  • 🖍️ Pastel/chalk fills - Soft chalky texture over paper tooth (fillStyle: 'pastel')
  • 📜 Paper ground - Cream sheet with grain and a soft vignette behind every chart
  • ✍️ Hand-guided strokes - Smooth-noise wobble, gentle bowing, and multi-pass pencil sketching instead of digital jitter
  • 🎨 Curated pigment palette - Watercolor-set default colors (ultramarine, burnt sienna, sap green, …)
  • 🌱 Deterministic rendering - Seeded randomness: the same chart drawn twice is the same drawing (seed option)
  • Fast, DOM-free geometry - All hand-drawn paths are computed numerically; no layout thrashing while rendering
  • 📊 Multiple chart types - Line graphs, bar charts, and pie charts
  • 🔧 TypeScript support - Full type definitions and IntelliSense
  • 🎯 Multi-series support - Handle complex datasets with ease
  • 🎭 Interactive tooltips - Hover effects with detailed information
  • 🎪 Directional scribble fills - Artistic fill patterns for charts
  • 🎨 Oil paint textures - Rich painterly tile fills
  • ⚙️ Highly configurable - Extensive customization options
  • 🧩 Modern architecture - Clean OOP design with proper separation of concerns

Installation

npm install handwritten-graph

Or via CDN:

<script src="https://unpkg.com/handwritten-graph@latest/dist/handwritten-graph.js"></script>

Quick Start

TypeScript/ES6 Modules

import { LineChart, BarChart, PieChart } from 'handwritten-graph';

// Sample data that can be reused across chart types
const chartData = {
  labels: ["Q1", "Q2", "Q3", "Q4"],
  datasets: [
    {
      label: "Revenue",
      data: [65, 59, 80, 81],
      lineColor: "rgb(75, 192, 192)", // For LineChart
      barColor: "#36A2EB" // For BarChart
    }
  ]
};

// Line Chart with Area Fill
const lineChart = new LineChart("#line-chart-container", chartData, {
  showArea: true,
  useScribbleFill: true
});

// Bar Chart (Vertical)
const barChart = new BarChart("#bar-chart-container", chartData, {
  orientation: 'vertical',
  showValues: true
});

// Horizontal Bar Chart
const horizontalBarChart = new BarChart("#horizontal-bar-container", chartData, {
  orientation: 'horizontal'
});

// Pie Chart
const pieData = [
  { label: "Marketing", value: 30, color: "#FF6384" },
  { label: "Development", value: 45, color: "#36A2EB" },
  { label: "Research", value: 15, color: "#FFCE56" },
  { label: "Administration", value: 10, color: "#4BC0C0" }
];

const pieChart = new PieChart("#pie-chart-container", pieData, {
  useScribbleFill: true,
  fillStyle: 'directional'
});

Legacy/JavaScript (Factory Functions)

// Using factory functions for backward compatibility
const lineCleanup = HandwrittenGraph.createGraph("#graph-container", chartData);
const barCleanup = HandwrittenGraph.createBarChart("#bar-container", chartData);
const pieCleanup = HandwrittenGraph.createPieChart("#pie-container", pieData);

// Clean up when done
lineCleanup();
barCleanup();
pieCleanup();

API Reference

Chart Classes

// Line Chart
new LineChart(selector: string, data: LineChartData, config?: Partial)

// Bar Chart  
new BarChart(selector: string, data: BarChartData, config?: Partial)

// Pie Chart
new PieChart(selector: string, data: PieChartData, config?: Partial)

Key Configuration Options

interface BaseChartConfig {
  width?: number;
  height?: number;
  handDrawnEffect?: boolean;
  useScribbleFill?: boolean; // Enable artistic fills (always on for pie charts)
  fillStyle?: 'watercolor' | 'pastel' | 'directional' | 'oilpaint';
  // Painting controls
  seed?: number;       // Deterministic wobble; same seed = identical drawing
  roughness?: number;  // 0 = ruler-straight … ~2 = very loose (default 1)
  sketchPasses?: number; // Pencil passes per stroke, 1-3 (default 2)
  paper?: boolean;     // Paper sheet behind the chart (default true)
  paperColor?: string; // Sheet tint (default warm cream)
  inkColor?: string;   // Axis/outline/text ink (default warm near-black)
}

// LineChart specific
interface LineChartConfig extends BaseChartConfig {
  showArea?: boolean; // Enable area fill under lines
  pointRadius?: number;
  lineColor?: string;
}

// BarChart specific  
interface BarChartConfig extends BaseChartConfig {
  orientation?: 'vertical' | 'horizontal'; // Chart orientation
  showValues?: boolean; // Show value labels on bars
  barSpacing?: number;
  groupSpacing?: number;
}

// PieChart specific
interface PieChartConfig extends BaseChartConfig {
  innerRadius?: number; // For donut charts
  legendBorder?: boolean;
}

Browser Support

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+
  • Modern mobile browsers

Development

# Install dependencies
npm install

# Development build with watch
npm run dev

# Production build
npm run build

# Testing
npm run test

Architecture

The library follows modern TypeScript patterns:

  • Object-Oriented Design: Charts are classes with proper encapsulation
  • Type Safety: Full TypeScript definitions with strict typing
  • Composition: Modular utilities and components
  • Inheritance: Base chart class with shared functionality
  • Factory Pattern: Backward-compatible factory functions
  • Strategy Pattern: Pluggable fill styles and effects

License

MIT License - see LICENSE file for details.

Watercolor & pastel painting

The default look is now a true painted wash, not a texture tile. Every shape (pie slice, bar, area) gets its own pigment: a wet base polygon, several translucent deposits that multiply where they overlap, interior pooling, and a darker rim where the wash "dries". One shared SVG filter feathers all edges.

// Watercolor is the default fill style — a pie chart needs no config at all
new PieChart('#pie', pieData);

// Watercolor area chart
new LineChart('#line', lineData, {
  showArea: true,
  useScribbleFill: true,
  fillStyle: 'watercolor'
});

// Chalky pastel bars on custom paper
new BarChart('#bars', barData, {
  useScribbleFill: true,
  fillStyle: 'pastel',
  paperColor: '#f6f1e5',
  seed: 7 // pick a different hand
});

// Prefer the old transparent background?
new PieChart('#pie', pieData, { paper: false });

Colors omitted from your datasets are assigned from WATERCOLOR_PALETTE (exported, along with PASTEL_PALETTE, INK_COLOR and PAPER_COLOR).

Notable default changes in v1.1.0

  • fillStyle defaults to 'watercolor' (was 'directional'); the legacy 'directional' and 'oilpaint' tile styles are still available.
  • Charts render on a paper background by default — set paper: false for the previous transparent look.
  • Default colors moved from d3.schemeCategory10 to the watercolor palette; explicit lineColor/barColor/color values are respected as before.
  • Rendering is deterministic: re-creating a chart with the same data no longer reshuffles the wobble. Pass a different seed to vary it.

Changelog

v1.1.0

  • NEW: Per-shape watercolor washes (fillStyle: 'watercolor', now the default) with layered translucent deposits, edge darkening, and interior pooling
  • NEW: Pastel/chalk fill style (fillStyle: 'pastel')
  • NEW: Paper background with grain and vignette (paper, paperColor)
  • NEW: Seeded deterministic rendering (seed), stroke roughness control (roughness), and multi-pass sketching (sketchPasses)
  • NEW: Curated watercolor pigment palette used for default series colors; palettes exported
  • ENHANCED: Hand-drawn strokes use smooth value noise + bowing (reads as a hand, not a tremor); axes, dots, and legend chips are drawn, not filtered
  • PERFORMANCE: All stroke/slice geometry is computed numerically — no more temporary SVG nodes appended to <body> for getPointAtLength measurement
  • PERFORMANCE: Color adjustments are pure math (previously one DOM element + getComputedStyle per tweak)
  • PERFORMANCE: One shared grain/edge filter set per chart instead of a filter pipeline per pattern; displacement filters applied per group, not per element
  • PERFORMANCE: Tooltip pointer tracking caches the chart's bounding rect per hover instead of measuring layout on every mousemove

v1.0.6

  • ENHANCED: Blob shapes improved to have better borders, and soft boundaries
  • ENHANCED: Improve pastel/pencil color conversion for hand-drawn aesthetics
  • OPTIMIZED: Improve rendering performance with reduced filter complexity
  • OPTIMIZED: Pattern caching system reduce memory footprint
  • FIXED: Improved scribble lines to cover fill areas properly

v1.0.5

  • NEW: BarChart support with vertical and horizontal orientations
  • NEW: Area fill support for LineCharts with showArea option
  • NEW: Multi-series support for BarCharts
  • NEW: Value labels on bar charts with showValues option
  • ENHANCED: Improved scribble fill patterns for all chart types
  • ENHANCED: Better responsive design and styling
  • ENHANCED: Seamless pie chart borders matching slice colors

v1.0.4

  • Update test suite
  • Add test coverage
  • Type check scripts
  • Type definition publish support

v1.0.3

  • Comprehensive test suite
  • Test Setup with D3 mocks
  • Example html to preview built lib

v1.0.2

  • Text elements with proper SVG property handling
  • Axes and grid styling
  • Line chart elements
  • Pie chart elements
  • Legend and Tooltip styling
  • Hand-drawn effects
  • Responsive design
  • Print styles

v1.0.1

  • Enhanced type definitions
  • Improved performance
  • Better error handling

v1.0.0

About

Handwritten graph library using typescript, typescript rewrite of handwritten linegraph project.

Topics

Resources

License

Stars

1 star

Watchers

1 watching

Forks

Packages

 
 
 

Contributors