atrament

repository·main·Indexed 23 days ago

https://github.com/jakubfiala/atrament

A lightweight JavaScript library for natural-feeling drawing and handwriting on the HTML Canvas. Version 5.1.0 focuses on smoothness and performance by drawing directly to the canvas bitmap. It supports multiple modes including drawing, erasing, and filling, as well as adaptive stroke width based on speed, pressure sensitivity, and stroke recording for undo/redo or SVG export functionality.

Tokens
3.3K
Snippets
6
Records
23
Agent score
82%

What's inside atrament

  1. Understand the Atrament data model

    main

    Atrament models drawing as a collection of independent strokes.

    • A stroke is a sequence of segments.
    • A segment contains:
      • point: An object with x and y coordinates.
      • time: Milliseconds since the stroke began.
      • pressure: A value from 0 to 1 (or 0.5 if no pressure data is available).
    • A stroke also captures the drawing settings (color, weight, etc.) active at the time of drawing.
  2. Enable Fill mode with a separate Worker

    main

    To keep the main bundle size small, the fill Worker is not bundled by default. If you want to use MODE_FILL, you must import the fill module separately and pass it to the Atrament constructor via the fill option.

    import Atrament from 'atrament';
    import fill from 'atrament/fill';
    
    const sketchpad = new Atrament({ fill });
  3. Initialize Atrament with a canvas

    main

    To use Atrament, create a <canvas> element in your HTML and pass the canvas object to the Atrament constructor in your JavaScript. You can optionally provide a configuration object to set the width, height, and default color.

    import Atrament from 'atrament';
    
    const canvas = document.querySelector('#sketchpad');
    const sketchpad = new Atrament(canvas, {
      width: 500,
      height: 500,
      color: 'orange',
    });
  4. Reconstruct strokes for Undo/Redo or Export

    main

    To implement undo/redo or SVG export, enable recordStrokes and use the strokerecorded event to save stroke data. You can then replay these strokes programmatically using beginStroke, draw, and endStroke.

    // 1. Enable recording
    atrament.recordStrokes = true;
    atrament.addEventListener('strokerecorded', ({ stroke }) => {
      // store `stroke` in an array for undo/redo
    });
    
    // 2. Replay a stroke
    // Set settings to match the recorded stroke
    atrament.mode = stroke.mode;
    atrament.weight = stroke.weight;
    // ... other settings
    
    const segments = stroke.segments.slice();
    const firstPoint = segments.shift().point;
    
    // Start the path
    atrament.beginStroke(firstPoint.x, firstPoint.y);
    
    let prevPoint = firstPoint;
    while (segments.length > 0) {
      const segment = segments.shift();
      // draw() returns the processed (smoothed) position
      const { x, y } = atrament.draw(
        segment.point.x, 
        segment.point.y, 
        prevPoint.x, 
        prevPoint.y, 
        segment.pressure
      );
      prevPoint = { x, y };
    }
    
    // Close the path
    atrament.endStroke(prevPoint.x, prevPoint.y);
  5. Manage drawing modes

    main

    Atrament supports several modes that change how the pointer interacts with the canvas. You can switch modes using the mode property.

    • MODE_DRAW ('draw'): Standard drawing mode using source-over compositing.
    • MODE_ERASE ('erase'): Erasing mode using destination-out compositing.
    • MODE_FILL ('fill'): Fill mode. Requires a FillWorker to be provided in the constructor. Triggers a fill operation on pointerdown.
    • MODE_DISABLED ('disabled'): Disables all drawing interactions.

    Note: MODE_FILL requires the fill option in the constructor to be a class that implements the worker interface.

  6. Initialize Atrament

    main

    To use Atrament, instantiate the Atrament class by passing a canvas selector (a string CSS selector or a HTMLCanvasElement) and an optional configuration object. Atrament manages pointer events and drawing logic on the provided canvas.

    Configuration Options:

    KeyTypeDescription
    weightnumberThe base thickness of the stroke.
    smoothingnumberSmoothing factor for lines.
    adaptiveStrokebooleanIf true, simulates ink discharge by varying thickness during a stroke.
    modestringInitial drawing mode (MODE_DRAW, MODE_ERASE, MODE_FILL, or MODE_DISABLED).
    secondaryMouseButtonbooleanIf true, prevents the default context menu when using the right mouse button.
    ignoreModifiersbooleanWhether to ignore keyboard modifiers.
    pressureLownumberScaling factor for low pressure.
    pressureHighnumberScaling factor for high pressure.
    pressureSmoothingnumberLow-pass filter factor for pressure changes.
    fillclassA FillWorker class required for MODE_FILL functionality.
    colorstringInitial stroke color (e.g., 'rgba(0,0,0,1)').
    widthnumberExplicit canvas width.
    heightnumberExplicit canvas height.
  7. Listen to Atrament events

    main

    Atrament provides several event hooks to track the drawing lifecycle:

    • dirty / clean: Fired when the canvas is first drawn on or cleared. Check sketchpad.dirty for state.
    • strokestart / strokeend: Fired when a stroke begins or ends. Returns x and y coordinates.
    • fillstart / fillend: (Fill mode only) fillstart includes x and y of the click.
    • pointerdown / pointerup: Fired before Atrament processes the stroke. Receives the raw PointerEvent.
    • strokerecorded: (Requires recordStrokes = true) Fired at strokeend with the full stroke data object.
    • segmentdrawn: (Requires recordStrokes = true) Fired during a stroke every time a segment is drawn.
  8. Configure Atrament drawing options

    main

    You can dynamically adjust several properties on the Atrament instance to change the drawing behavior:

    • clear(): Clears the canvas.
    • weight: Sets line thickness in pixels.
    • color: Sets the stroke color (CSS compatible).
    • mode: Sets the current tool. Use constants from the atrament package: MODE_DRAW (default), MODE_ERASE, MODE_FILL, or MODE_DISABLED.
    • smoothing: Adjusts adaptive smoothing (default 0.85). Higher values are smoother; lower values are more responsive.
    • adaptiveStroke: Toggles line width variation based on speed (default true).
    • pressureLow / pressureHigh: Sets the bounds for the pressure scale.
    • pressureSmoothing: Amount of low-pass filtering for pressure (0-1, default 0.3).
    • secondaryMouseButton: Enables drawing with the right mouse button (default false).
    • ignoreModifiers: If true, ignores strokes made while holding modifier keys like Alt/Ctrl/Cmd (default false).
    • recordStrokes: Enables the strokerecorded event (default false).
    import { MODE_DRAW, MODE_ERASE, MODE_FILL, MODE_DISABLED } from 'atrament';
    
    sketchpad.mode = MODE_DRAW;
    sketchpad.weight = 20;
    sketchpad.color = '#ff485e';
    sketchpad.smoothing = 1.3;
    sketchpad.adaptiveStroke = false;
    sketchpad.pressureLow = 0;
    sketchpad.pressureHigh = 2;
    sketchpad.pressureSmoothing = 0.4;
    sketchpad.secondaryMouseButton = true;
    sketchpad.ignoreModifiers = true;
    sketchpad.recordStrokes = true;
  9. Convert hex colors to RGB arrays with hexToRgb()

    main
    Use hexToRgb(hexColor) to transform a hex color string (e.g., #ffffff or ffffff) into an array of three integers representing the Red, Green, and Blue channels. This is useful when converting user-provided hex inputs into the RGB format required by ImageData.
  10. Configure stroke weight and color

    main

    You can dynamically adjust the appearance of the stroke using the weight and color properties.

    • weight: Sets the base thickness of the stroke. This affects both the current drawing and future strokes.
    • color: Sets the stroke color as a string (e.g., '#ff0000' or 'rgba(0,0,0,0.5)').
  11. Paint pixels with alpha blending using pixelPainterMixAlpha()

    main

    The pixelPainterMixAlpha(data, fillR, fillG, fillB, fillA) function returns a function that performs alpha-blending when painting a pixel. It calculates a mix ratio based on the existing alpha value of the pixel to blend the new color with the old color.

    Returns:

    • A function that accepts pixelPos and performs the blended write operation.