Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Polygon Vertex Dragging for Shape Modification in Fabric.js

Tech 3

This guide demonstrates a method for dynamically altering a polygon's shape by dragging its vertices using Fabric.js. While the official Fabric.js demos offer a more sophisticated approach using custom controls, this tutorial presents a simplified version for clarity and learning purposes.

Core Concept

The functionality is achieved by overlaying interactive circualr handles on each polygon vertex. When a user drags one of these circles, the corresponding polygon point updates its position.

Implementation Steps

  1. Initialize a Fabric.js canvas.
  2. Create a polygon object with direct user interaction disabled.
  3. Generate a draggable circle (handle) for each polygon vertex.
  4. Listen for object movement events; if a handle circle is moved, update the polygon's vertex coordinates.
  5. Refresh the canvas to reflect the changes.

Polygon Configuration

To prevent direct manipulation of the polygon itself, configure it with the following properties:

const myPolygon = new fabric.Polygon(vertices, {
    fill: 'red',
    stroke: 'black',
    strokeWidth: 2,
    objectCaching: false, // Crucial for real-time updates
    selectable: false,    // Prevents selection
    evented: false        // Makes it non-interactive
});

Handle Circle Configuration

Each circular handle should be configured to act as a control point:

new fabric.Circle({
    left: vertexX,
    top: vertexY,
    radius: 10,
    fill: 'white',
    stroke: '#333',
    strokeWidth: 3,
    originX: 'center',    // Position refers to circle's center
    originY: 'center',
    hasControls: false,   // Hide resize controls
    hasBorders: false,    // Hide selection border
    customId: index       // Identifier linking circle to vertex
})

Complete Working Example

<canvas id="drawingCanvas" width="600" height="500"></canvas>
<script src="https://unpkg.com/fabric@5.3.0/dist/fabric.min.js"></script>
<script>
    const canvas = new fabric.Canvas('drawingCanvas');

    // Define initial polygon vertices
    const vertexCoordinates = [
        {x: 100, y: 100},
        {x: 180, y: 60},
        {x: 260, y: 100},
        {x: 240, y: 220},
        {x: 120, y: 180}
    ];

    // Create the base polygon
    const shape = new fabric.Polygon(vertexCoordinates, {
        fill: 'rgba(255,0,0,0.5)',
        stroke: 'black',
        strokeWidth: 2,
        objectCaching: false,
        selectable: false,
        evented: false
    });

    const handles = [];
    // Create a draggable handle for each vertex
    vertexCoordinates.forEach((coord, idx) => {
        const handle = new fabric.Circle({
            left: coord.x,
            top: coord.y,
            radius: 12,
            fill: '#fff',
            stroke: '#666',
            strokeWidth: 4,
            originX: 'center',
            originY: 'center',
            hasControls: false,
            hasBorders: false,
            handleIndex: idx // Custom property to track vertex
        });
        handles.push(handle);
    });

    // Add all objects to canvas
    canvas.add(shape, ...handles);

    // Update polygon when a handle is dragged
    canvas.on('object:moving', function(event) {
        const movedObj = event.target;
        // Check if the moved object is one of our handles
        if (movedObj.handleIndex !== undefined) {
            const pointIndex = movedObj.handleIndex;
            // Update the corresponding polygon vertex
            shape.points[pointIndex].x = movedObj.left;
            shape.points[pointIndex].y = movedObj.top;
            // Force canvas redraw
            canvas.requestRenderAll();
        }
    });
</script>

Key Points

  • Setting objectCaching: false on the polygon is essential for visual updates.
  • The handleIndex custom property creates the link between a circle and a specific polygon vertex.
  • Using canvas.requestRenderAll() ensures the polygon redraws with the new vertex positions.

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.