Pencil Brush in Fabric.js

Regular Configuration

Enable Drawing Mode

To use the pencil tool, first enable drawing mode by setting isDrawingMode to true when initializing the canvas. Here’s the base code:

<canvas id="fabricCanvas" width="500" height="400" style="border: 1px solid #ccc;"></canvas>

<script>
  const fabricCanvas = new fabric.Canvas('fabricCanvas', {
    isDrawingMode: true // Enable drawing mode
  });
</script>

With isDrawingMode: true, you can draw by holding the left mouse button on the canvas.

Register the Pencil Brush

To use the pencil tool, set canvas.freeDrawingBrush to an instance of fabric.PencilBrush.

// ... (previous setup code)

const fabricCanvas = new fabric.Canvas('fabricCanvas', {
  isDrawingMode: true
});

// Instantiate the pencil brush
const myPencilBrush = new fabric.PencilBrush(fabricCanvas);
// Assign the pencil brush to the canvas
fabricCanvas.freeDrawingBrush = myPencilBrush;

Note: The canvas instance must be passed when creating fabric.PencilBrush. Alternatively, use the initialize method:

// ... (previous setup code)

// Create the pencil brush
const myPencilBrush = new fabric.PencilBrush();
// Initialize with the canvas
myPencilBrush.initialize(fabricCanvas);
// Assign to the canvas
fabricCanvas.freeDrawingBrush = myPencilBrush;

Set Pencil Color

Use the color property to define the pencil’s color. Supports color keywords, hex values, or RGBA:

myPencilBrush.color = 'pink'; // Keyword-based color
// Or with transparency
myPencilBrush.color = 'rgba(0, 0, 0, 0.1)'; // Semi-transparent black

Set Pencil Width

The width property (numeric value) controls the pencil’s thickness (in pixels):

myPencilBrush.width = 10; // Adjust thickness

Shadow

Create a shadow with fabric.Shadow and assign it to the shadow property. For clarity, we thicken the pencil:

myPencilBrush.width = 10; // Thicken for visibility
myPencilBrush.shadow = new fabric.Shadow({
  blur: 10,    // Blur intensity (pixels)
  offsetX: 10, // Horizontal offset (pixels)
  offsetY: 10, // Vertical offset (pixels)
  color: '#30e3ca' // Shadow color
});

Dashed Lines

Use strokeDashArray to create dashed line patterns. The array defines the repeating sequence (solid/dashed lengths):

  • [10]: 10px solid → 10px dashed (repeats)
  • [30, 10]: 30px solid → 10px dashed (repeats)
  • [10, 20, 30]: 10px solid → 20px dashed → 30px solid (repeats)
myPencilBrush.strokeDashArray = [30, 10]; // 30px solid, 10px dashed

Line Cap

The strokeLineCap property defines the line’s end style. Options: butt, round (default), or square:

myPencilBrush.width = 10; // Thicken for visibility
myPencilBrush.strokeLineCap = 'square'; // Square-ended lines

Corner Style (Line Join)

Use strokeLineJoin to set how corner are rendered. Options: bevel, round, or miter:

myPencilBrush.strokeLineJoin = 'miter'; // Sharp corners (use with strokeMiterLimit)

Miter Limit

When strokeLineJoin = 'miter', strokeMiterLimit controls the maximum miter langth (prevents excessively long corners):

myPencilBrush.strokeMiterLimit = 20;

Corner Smoothness (Decimate)

The decimate property adjusts corner smoothness (higher values = smoother corners):

myPencilBrush.width = 5;
myPencilBrush.decimate = 40; // Increase smoothness

Limit to Canvas

Set limitedToCanvasSize to true to prevent drawing outside the canvas boundaries:

myPencilBrush.limitedToCanvasSize = true;

Draw Straight Lines

By default, holding Shift draws straight lines. Customize the modifier key with straightLineKey:

myPencilBrush.straightLineKey = 'shiftKey'; // Default: 'shiftKey'
// Other options: 'altKey', 'ctrlKey', 'none', undefined, null

Events

Before Path Creation: before:path:created

Triggered before the drawing path is finalized (useful for pre-processing):

fabricCanvas.on('before:path:created', (options) => {
  console.log(options.path); // The in-progress path object
});

After Path Creation: path:created

Triggered when the drawing path is complete (useful for post-processing):

fabricCanvas.on('path:created', (options) => {
  console.log(options.path); // The finalized path object
});

Mouse Down: onMouseDown

Customize the mouse-down behavior (use a regular function to preserve this context):

myPencilBrush.onMouseDown = function(point, event) {
  console.log(point); // {x, y} coordinates of the mouse
  console.log(event); // Event details (including original DOM event)

  if (this.canvas._isMainEvent(event.e)) {
    this.drawStraightLine = event.e[this.straightLineKey];
    this._prepareForDrawing(point);
    this._captureDrawingPath(point);
    this._render();
  }
};

Mouse Move: onMouseMove

Customize the mouse-move behavior (renders the live drawing):

myPencilBrush.onMouseMove = function(point, event) {
  console.log(point);
  console.log(event);

  if (this.canvas._isMainEvent(event.e)) {
    this.drawStraightLine = event.e[this.straightLineKey];
    if (!this.limitedToCanvasSize || !this._isOutSideCanvas(point)) {
      if (this._captureDrawingPath(point) && this._points.length > 1) {
        if (this.needsFullRender()) {
          this.canvas.clearContext(this.canvas.contextTop);
          this._render();
        } else {
          const points = this._points;
          const ctx = this.canvas.contextTop;

          this._saveAndTransform(ctx);
          if (this.oldEnd) {
            ctx.beginPath();
            ctx.moveTo(this.oldEnd.x, this.oldEnd.y);
          }
          this.oldEnd = this._drawSegment(ctx, points[points.length - 2], points[points.length - 1], true);
          ctx.stroke();
          ctx.restore();
        }
      }
    }
  }
};

Mouse Up: onMouseUp

Customize the mouse-up behavior (finalizes the drawing):

myPencilBrush.onMouseUp = function(point) {
  console.log(point); // {x, y} coordinates of the mouse release

  if (this.canvas._isMainEvent(point.e)) {
    this.drawStraightLine = false;
    this.oldEnd = undefined;
    this._finalizeAndAddPath();
    return false;
  }
  return true;
};

Tags: fabric.js pencil brush Canvas javascript drawing tool

Posted on Sat, 03 Oct 2026 16:16:50 +0000 by twopeak