turash/bugulma/frontend/lib/pixel-art/README.md
Damir Mukimov 6347f42e20
Consolidate repositories: Remove nested frontend .git and merge into main repository
- Remove nested git repository from bugulma/frontend/.git
- Add all frontend files to main repository tracking
- Convert from separate frontend/backend repos to unified monorepo
- Preserve all frontend code and development history as tracked files
- Eliminate nested repository complexity for simpler development workflow

This creates a proper monorepo structure with frontend and backend
coexisting in the same repository for easier development and deployment.
2025-11-25 06:02:57 +01:00

7.5 KiB

Pixel Art Library

A comprehensive TypeScript library for creating pixel-perfect icons, logos, and sprites using HTML5 Canvas API. Optimized for performance with efficient algorithms and batch operations.

Features

  • 🎨 Pixel-Perfect Rendering - Crisp, clean pixel art with no anti-aliasing
  • Performance Optimized - Batch pixel operations, color caching, and efficient algorithms
  • 🎨 Color Palette Management - Predefined and custom color palettes with caching
  • 🎨 Shape Helpers - Easy-to-use functions for common shapes
  • 🎨 Gradient Support - Linear and radial gradients
  • 🎨 Layer System - Compose complex icons from multiple layers
  • 🎨 Type-Safe - Full TypeScript support
  • 🌐 Browser Compatible - Enhanced cross-browser support for pixel rendering
  • 📐 Advanced Algorithms - Bresenham line algorithm, midpoint circle algorithm

Installation

The library is already included in the project. Import from:

import { PixelArtRenderer, PALETTES, createCircle } from '@/lib/pixel-art';

Quick Start

Basic Usage

import { PixelArtRenderer, PALETTES, createCircle } from '@/lib/pixel-art';

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d')!;

const renderer = new PixelArtRenderer(ctx, { width: 32, height: 32, scale: 2 }, PALETTES.warm);

// Draw a circle
renderer.circle(createCircle(16, 16, 10), renderer.color('crustLight'));

React Component Example

import React, { useRef, useEffect } from 'react';
import { PixelArtRenderer, PALETTES, createCircle } from '@/lib/pixel-art';

const MyIcon: React.FC<{ size?: number }> = ({ size = 64 }) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    const renderer = new PixelArtRenderer(
      ctx,
      { width: 32, height: 32, scale: size / 32 },
      PALETTES.warm
    );

    renderer.clear();
    renderer.circle(createCircle(16, 16, 10), renderer.color('crustLight'));
  }, [size]);

  return (
    <canvas ref={canvasRef} width={size} height={size} style={{ imageRendering: 'pixelated' }} />
  );
};

API Reference

PixelArtRenderer

Main rendering class for pixel art.

Constructor

new PixelArtRenderer(
  ctx: CanvasRenderingContext2D,
  config: PixelArtConfig,
  palette?: ColorPalette
)

Methods

Basic Drawing:

  • clear() - Clear the canvas
  • pixel(x, y, color, alpha?) - Draw a single pixel (with bounds checking)
  • pixels(points[]) - Draw multiple pixels efficiently using ImageData batch operations
  • rect(rect, color, alpha?) - Draw a rectangle
  • rectOutline(rect, color, lineWidth?, alpha?) - Draw rectangle outline
  • circle(circle, color, alpha?) - Draw a filled circle (optimized midpoint algorithm)
  • circleOutline(circle, color, lineWidth?, alpha?) - Draw circle outline
  • triangle(triangle, color, alpha?) - Draw a triangle
  • triangleOutline(triangle, color, lineWidth?, alpha?) - Draw triangle outline
  • polygon(points[], color, alpha?) - Draw a filled polygon (scanline algorithm)
  • line(from, to, color, lineWidth?, alpha?) - Draw a line (Bresenham algorithm for pixel-perfect lines)

Gradients:

  • linearGradient(gradient, shape, alpha?) - Draw with linear gradient
  • radialGradient(gradient, shape, alpha?) - Draw with radial gradient

Advanced:

  • drawLayers(layers) - Draw multiple layers with blend modes
  • sprite(data, palette) - Draw sprite from 2D array
  • pattern(pattern, bounds) - Draw custom pattern (optimized for batch operations)
  • getImageData() - Get current canvas as ImageData for processing
  • putImageData(imageData, dx?, dy?) - Draw ImageData to canvas

Color Management:

  • color(colorName) - Get color from palette (cached for performance)
  • setPalette(palette) - Update palette and clear cache
  • clearColorCache() - Clear color cache manually

Shape Helpers

  • createRect(x, y, width, height) - Create rectangle
  • createCircle(x, y, radius) - Create circle
  • createTriangle(p1, p2, p3) - Create triangle
  • createEquilateralTriangle(centerX, centerY, size) - Create equilateral triangle
  • createPoint(x, y) - Create point
  • createStar(centerX, centerY, outerRadius, innerRadius, points) - Create star
  • createHeart(centerX, centerY, size) - Create heart shape
  • createDiamond(centerX, centerY, width, height) - Create diamond

Color Palettes

Predefined palettes:

  • PALETTES.warm - Warm tones (gold, brown, red)
  • PALETTES.cool - Cool tones (blue, cyan)
  • PALETTES.earth - Earth tones (brown, green, beige)
  • PALETTES.vibrant - Vibrant colors
  • PALETTES.monochrome - Black and white

Custom Palette

import { createPalette } from '@/lib/pixel-art';

const myPalette = createPalette('Custom', {
  primary: '#FF0000',
  secondary: '#00FF00',
  accent: '#0000FF',
});

Examples

Creating a Simple Icon

const renderer = new PixelArtRenderer(ctx, { width: 32, height: 32 }, PALETTES.warm);

// Background
renderer.rect({ x: 0, y: 0, width: 32, height: 32 }, renderer.color('background'));

// Main shape
renderer.circle(createCircle(16, 16, 12), renderer.color('crustLight'));

// Details
renderer.circle(createCircle(16, 16, 8), renderer.color('meatLight'));

Using Gradients

const gradient: LinearGradient = {
  x1: 0,
  y1: 0,
  x2: 32,
  y2: 32,
  stops: [
    { offset: 0, color: renderer.color('crustLight') },
    { offset: 1, color: renderer.color('crustDark') },
  ],
};

renderer.linearGradient(gradient, createRect(0, 0, 32, 32));

Layer System

const layers: PixelArtLayer[] = [
  {
    name: 'background',
    draw: (ctx) => {
      renderer.rect({ x: 0, y: 0, width: 32, height: 32 }, renderer.color('background'));
    },
  },
  {
    name: 'foreground',
    opacity: 0.8,
    draw: (ctx) => {
      renderer.circle(createCircle(16, 16, 10), renderer.color('crustLight'));
    },
  },
];

renderer.drawLayers(layers);

Performance Tips

  1. Batch Operations - Use pixels() method for drawing many pixels at once (automatically used by pattern() for large patterns)
  2. Color Caching - Colors are automatically cached; use setPalette() when changing palettes
  3. Efficient Algorithms - Lines use Bresenham's algorithm, circles use midpoint algorithm for optimal performance
  4. ImageData Operations - Use getImageData() and putImageData() for advanced effects and filters

Best Practices

  1. Use Logical Coordinates - Work in logical pixel space (e.g., 32x32), let the renderer handle scaling
  2. Reuse Palettes - Define palettes once and reuse across icons (caching improves performance)
  3. Layer Composition - Break complex icons into layers for maintainability
  4. Pixel-Perfect - Keep antialiasing: false for crisp pixel art
  5. Type Safety - Use TypeScript types for all shapes and configurations
  6. Batch When Possible - For drawing many pixels, use pixels() instead of multiple pixel() calls
  7. Browser Compatibility - The library automatically handles cross-browser pixel rendering differences

Architecture

lib/pixel-art/
├── index.ts          # Main exports
├── types.ts          # TypeScript type definitions
├── renderer.ts       # Core rendering engine
├── palettes.ts       # Color palette management
├── shapes.ts         # Shape helper functions
└── README.md         # This file

License

Part of the Туган Як (Native Land) project.