Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Customizing Selection Appearance and Behavior in Fabric.js

Tech 2

When an object is selected on a Fabric.js canvas, its visual representation changes. This includes the appearance of control handles, the selection border, and other interactive states. This guide covers the properties and methods available to customize this selection state.

Initial Setup

First, create a basic canvas and add a shape to work with.

<canvas id="myCanvas" style="border: 1px solid #ccc;"></canvas>

<script>
  const canvas = new fabric.Canvas('myCanvas', {
    width: 400,
    height: 400,
  })

  const ellipse = new fabric.Ellipse({
    top: 80,
    left: 80,
    rx: 60, // Horizontal radius
    ry: 40, // Vertical radius
    fill: '#a8d8ea'
  })

  canvas.add(ellipse)
</script>

Control Handles (Corners)

Control handles are the interactive points that appear around a selected object, used for scaling and rotating.

Solid vs. Hollow Handles

By default, control handles are hollow (transparent). To make them solid, set the transparentCorners property to false.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  transparentCorners: false // Handles are now solid
})

Handle Color

Use the cornerColor property to set the fill color of the control handles.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  transparentCorners: false,
  cornerColor: 'green' // Solid green handles
})

Handle Stroke Color

To set the border color of the handles independently, use the cornerStrokeColor property.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  transparentCorners: false,
  cornerColor: 'green',
  cornerStrokeColor: 'darkblue' // Blue border on green handles
})

Handle Size

Adjust the size of the control handles with the cornerSize property.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  cornerSize: 18 // Larger handles
})

Handle Border Dash Pattern

Create dashed borders for the control handles using the cornerDashArray property. It accepts an array of numbers defining the dash pattern.

  • [5]: Equal dash and gap length.
  • [5, 10]: 5px dash, 10px gap.
  • [5, 10, 15]: 5px dash, 10px gap, 15px dash, 5px gap, 10px dash... (repeats).
const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  cornerSize: 18,
  cornerDashArray: [5, 10] // Dashed border pattern
})

Handle Shape

Change the handle shape from square to circle using the cornerStyle property.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  cornerStyle: 'circle' // Circular handles
})

Selection Border (Bounding Box)

The rectangular border that appears around a selected object is often called the selection border or bounding box.

Border Color

Set the color of the selection border with the borderColor property.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  borderColor: 'purple' // Purple selection border
})

Border Thickness

Control the thickness of the selection border using the borderScaleFactor property. The base border width is multiplied by this value.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  borderScaleFactor: 3 // Thicker border
})

Border Dash Pattern

Similar to control handles, the selection border can also be dashed using the borderDashArray property.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  borderDashArray: [15, 5, 3, 5] // Complex dash pattern
})

Additional Styling

Padding

Internal padding can be added between the object's visual bounds and the selection border/control handles using the padding property.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  padding: 25 // Increased space between object and selection UI
})

Background Colors

Fabric.js distinguishes between fill color and background color. The backgroundColor property fills the rectangular area the object occupies (its bounding box). The selectionBackgroundColor fills the area between the object and the selection border, which is only visible when padding is applied.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  backgroundColor: 'lightgray', // Fills the object's bounding box area
  padding: 20,
  selectionBackgroundColor: 'rgba(0, 200, 0, 0.3)' // Green tint in padded area when selected
})

Opacity During Movement

Reduce the opacity of the selection UI (handles and border) while the object is being dragged using borderOpacityWhenMoving. Accepts a value from 0 (transparent) to 1 (opaque).

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  borderOpacityWhenMoving: 0.3 // Very faint selection UI while moving
})

Selection State and Behavior

Disabling Selection

Prevent an object from being seelcted entirely by setting selectable to false.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  selectable: false // Cannot be clicked to select
})

Pixel-Perfect Selection

By default, clicking anywhere within an object's rectangular bounding box will select it. For non-rectangular shapes (like circles), this includes "empty" corners. Setting perPixelTargetFind to true restricts selection to the actual painted pixels of the object.

const circle = new fabric.Circle({
  radius: 50,
  fill: 'red',
  perPixelTargetFind: true // Must click on the red circle itself
})

Hiding Control Handles

Hide all control handles by setting hasControls to false. This prevents scaling and rotation via handles.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  hasControls: false // No handles visible
})

Hiding the Selection Border

Hide the selection border by setting hasBorders to false.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
  hasBorders: false // No border visible when selected
})

Controlling Individual Handle Visibility

You can show or hide specific control handles. The handles are identified by keys: tl (top-left), tr (top-right), br (bottom-right), bl (bottom-left), ml (middle-left), mt (middle-top), mr (middle-right), mb (middle-bottom), mtr (middle-top for rotation).

Use setControlVisible(controlKey, visible) for a single handle, or setControlsVisibility(options) for multiple handles.

const rect = new fabric.Rect({
  width: 100,
  height: 100,
  fill: 'orange',
})

// Hide the top-left and bottom-right handles
rect.setControlsVisibility({
  tl: false,
  br: false
})

// Alternatively, hide the bottom-left handle individually
rect.setControlVisible('bl', false)

Checking Handle Visibility

Use isControlVisible(controlKey) to check if a specific handle is currently visible.

rect.setControlVisible('tl', false)
console.log(rect.isControlVisible('tl')) // false
console.log(rect.isControlVisible('tr')) // true (default)

Retrieving the Currently Selected Object

Use canvas methods to get the active selection.

  • canvas.getActiveObject(): Returns the single currently active object, or null.
  • canvas.getActiveObjects(): Returns an array of all currently selected objects (useful for multi-selection), or an empty array.
// Example: Change fill color of the selected object
canvas.on('selection:created', function() {
  const activeObj = canvas.getActiveObject()
  if (activeObj) {
    activeObj.set('fill', 'cyan')
    canvas.renderAll()
  }
})

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.