quadtree-ts

2.2.2

Simple Example

Click the buttons to add elements to the Quadtree. After adding five objects, the Quadtree it will split, because maxObjects: 4 was set (default: 10).

The following code is reduced to the most important parts. View the full script.js of this example on GitHub.

HTML

<canvas id="canvas" width="640" height="480"></canvas>
<button id="btnAdd">add small object</button>

JS

// Create a new Quadtree
const tree = new Quadtree({
	width: 640,
	height: 480,
    maxObjects: 4,
});

// Store all objects in an array
const myObjects = [];

// Canvas and context
const canvas = document.querySelector('#canvas'),
    ctx = canvas.getContext('2d');

// Add event listener to a button to create new Rectangles
document.querySelector('#btnAdd').addEventListener('click', () => {

    // Each primitive requires geometry properties –
    // For Rectangle x, y, width and height are required.
    const rect = new Quadtree.Rectangle({
        x: Math.random() * 640,
        y: Math.random() * 480,
        width: 4 + Math.random() * 28,
        height: 4 + Math.random() * 28,

        // We will use the optional `data` property to 
        // keep track of the object's status
        data: {
            check: false
        },
    });

    // Insert the rect in the Quadtree
    tree.insert(rect);

    // Store all objects for later use
    myObjects.push(rect);

    // Update the scene
    draw();
});

// Add event listener to a button to remove existing Rectangles
document.querySelector('#btnRemove').addEventListener('click', () => {
    if(myObjects.length > 0) {
        
        // Remove from Quadtree first
        tree.remove(myObjects[0]);
        
        // Remove from datakeeping
        myObjects.splice(0, 1);

        // Update the scene
        draw();
    }
});

// Create a "cursor" Rectangle to retrieve objects from the Quadtree
const myCursor = new Quadtree.Rectangle({
    x: 0,
    y: 0,
    width: 28,
    height: 28
});

// Add event listener to mouse movement
canvas.addEventListener('mousemove', (e) => {
    myCursor.x = e.offsetX - (myCursor.width/2);
    myCursor.y = e.offsetY - (myCursor.height/2);

    // Reset check flag on each Rectangle
    myObjects.forEach(rect => rect.data.check = false);

    // Retrieve all objects that share nodes with the cursor 
    const candidates = tree.retrieve(myCursor);

    // Flag retrieved objects
    candidates.forEach(rect => rect.data.check = true);

    // Update the scene
    draw();
});

function draw() {
    
    // Clear the canvas
    ctx.clearRect(0, 0, 640, 480);
    
    // Draw the objects
    for(let i=0;i<myObjects.length;i=i+1) {
        const obj = myObjects[i];
        ctx.fillStyle = obj.data.check ? 'rgba(127,255,212,0.8)' : 'rgba(255,255,255,0.25)';
        ctx.fillRect(obj.x, obj.y, obj.width, obj.height);
    }

    // Draw the cursor
    ctx.strokeStyle = 'rgba(127,255,212,1)';
    ctx.strokeRect(myCursor.x, myCursor.y, myCursor.width, myCursor.height);
};

To see the full example code please check the page source or visit this page on github.