Skip to content

PixiJS Drag and Drop — Interactive Element Dragging

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about PixiJS Drag and Drop. We cover key concepts, practical examples, and best practices to help you master this topic.

PixiJS drag and drop enables interactive element dragging with pointer events for both mouse and touch input.

What You'll Learn

By the end of this guide, you will make sprites draggable with pointer events, implement drop zone detection, add snap-to-grid behavior, build sortable lists, and handle concurrent touch and mouse input.

Basic Draggable

sprite.interactive = true;
sprite.cursor = 'grab';

sprite.on('pointerdown', onDragStart)
      .on('pointerup', onDragEnd)
      .on('pointerupoutside', onDragEnd)
      .on('pointermove', onDragMove);

var dragData = null;

function onDragStart(event) {
    dragData = event.data;
    this.alpha = 0.7;
    this.dragging = true;
}

function onDragMove() {
    if (this.dragging) {
        var pos = dragData.getLocalPosition(this.parent);
        this.x = pos.x;
        this.y = pos.y;
    }
}

function onDragEnd() {
    this.alpha = 1;
    this.dragging = false;
    dragData = null;
}

Snap to Grid

function onDragMove() {
    if (this.dragging) {
        var pos = dragData.getLocalPosition(this.parent);
        this.x = Math.round(pos.x / 50) * 50;
        this.y = Math.round(pos.y / 50) * 50;
    }
}

Drop Zone

dropZone.interactive = true;
dropZone.hitArea = new PIXI.Rectangle(0, 0, 100, 100);

function onDragEnd() {
    this.alpha = 1;
    this.dragging = false;
    dragData = null;

    if (dropZone.getBounds().contains(this.x, this.y)) {
        this.position.set(
            dropZone.x + dropZone.width / 2,
            dropZone.y + dropZone.height / 2
        );
        console.log('Dropped in zone!');
    }
}

Common Mistakes

1. Forgetting interactive = true

Sprites are not interactive by default. Set interactive = true to receive pointer events.

2. Using click Instead of pointer

Use pointerdown, pointermove, pointerup for unified mouse and touch handling.

3. Not Using getLocalPosition

Direct event.clientX/Y gives canvas coordinates. Use getLocalPosition for scene coordinates.

4. Dragging Outside Bounds

Without bounds checking, elements can be dragged off-screen. Clamp x, y after calculation.

5. Not Handling pointerupoutside

If the pointer moves off the sprite and releases, pointerupoutside fires but dragging should still end.

Practice Questions

Q1: How do you make a sprite draggable? A: Set interactive = true, then handle pointerdown, pointermove, pointerup events.

Q2: What event fires when dragging ends outside the sprite? A: pointerupoutside.

Q3: How do you get the correct drag position? A: Use event.data.getLocalPosition(sprite.parent).

Q4: How do you limit dragging to bounds? A: Clamp x and y after each pointermove.

Q5: How do you detect drop on a target? A: Check if the dragged sprite's position is within the target's bounds.

Challenge: Build a puzzle where pieces snap to a 3x3 grid. When all pieces are in correct positions, show a completion message. Pieces should animate back if dropped outside the grid.

FAQ

Does dragging work on touch devices?

Yes. Pointer events handle both mouse and touch.

How do I change cursor on hover?

Set sprite.cursor = 'pointer' or 'grab'.

Can I constrain drag to one axis?

Yes. Update only x or y during pointermove.

How do I make a drag handle?

Check if the pointerdown position is within a specific area before starting drag.

Can I drag multiple objects at once?

Yes. Track multiple dragData references and update each.

Try It Yourself

Build a draggable shape.

<!DOCTYPE html>
<html>
<head>
    <title>PixiJS Drag Drop</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/7.3/pixi.min.js"></script>
</head>
<body style="font-family:sans-serif;padding:20px;">
<h2>Drag the Shapes</h2>
<script>
var app = new PIXI.Application({ width: 500, height: 350, background: 0xf5f5f5 });
document.body.appendChild(app.view);

var shapes = [
    { color: 0x4ecdc4, x: 80, y: 100 },
    { color: 0xff6b35, x: 200, y: 150 },
    { color: 0x2a9d8f, x: 320, y: 120 }
];

shapes.forEach(function(s) {
    var g = new PIXI.Graphics();
    g.beginFill(s.color);
    g.drawRoundedRect(0, 0, 60, 60, 8);
    g.endFill();
    g.x = s.x;
    g.y = s.y;
    g.interactive = true;
    g.cursor = 'grab';

    g.on('pointerdown', function(event) {
        this.alpha = 0.7;
        this.dragging = true;
        this.dragData = event.data;
        this.parent.setChildIndex(this, this.parent.children.length - 1);
    });

    g.on('pointermove', function() {
        if (this.dragging) {
            var pos = this.dragData.getLocalPosition(this.parent);
            this.x = Math.max(0, Math.min(440, pos.x - 30));
            this.y = Math.max(0, Math.min(290, pos.y - 30));
        }
    });

    g.on('pointerup', function() {
        this.alpha = 1;
        this.dragging = false;
    });

    g.on('pointerupoutside', function() {
        this.alpha = 1;
        this.dragging = false;
    });

    app.stage.addChild(g);
});
</script>
</body>
</html>

What's Next

Master interaction events.

Interaction — Event handling and interaction. Render Textures — Render textures.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro