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;
};