Search code examples
javascriptcanvaspaperjs

handle scroll on canvas view - paperjs


http://40.117.122.212/

I want to add more images dynamically on scrolling the canvas, i don't wanna see any empty areas on the canvas.

Any ideas on how to get that done ?

I use paperjs, I create about 90 images and they are moving on the canvas randomly.


Solution

  • Each time you scroll, you can check if there is space for more images at the bottom of the screen (and maybe at the top too for a better effect?) and if this is true, add more images.
    In order to get that working, you will certainly need to find a way to quickly get the topest/lowest items to check how far they are from view bounds.

    To better understand the concept, I reduced the problem to a simple case involving only one column of circles.
    Here is the sketch demonstrating the solution.
    Code should be self-explainatory and should allow you to transpose it to your specific case.

    // Set gris Size.
    const gridSize = 100;
    
    // Calculate and store several useful metrics.
    const viewHeight = view.bounds.height;
    const itemsCount = Math.floor(viewHeight / gridSize);
    
    // For the simplicity of the demo, items are only drawn in one column so x
    // coordinate is constant.
    const x = view.center.x;
    
    // Create original items to fill the screen.
    let items = [];
    for (let i = 0; i < itemsCount; i++) {
        items.push(createItem(i * gridSize));
    }
    
    // Center them on the screen.
    project.activeLayer.position = view.center;
    
    // On scroll...
    view.element.onmousewheel = function(event) {
        // ...translate layer up or down.
        // Using layer translation instead of view scroll cause items coordinates
        // to be updated which will help us in later calculations.
        const translation = event.deltaY > 0 ? new Point(0, 10) : new Point(0, -10);
        project.activeLayer.translate(translation);
    
        // Trigger items addition process.
        addItemsIfNeeded();
    };
    
    // Simply create a random colored, horizontally centered circle, at given
    // y position.
    function createItem(y) {
        return new Path.Circle({
            center: new Point(x, y),
            radius: gridSize / 4,
            fillColor: Color.random()
        });
    }
    
    // Check for empty space at the bottom or the top of the page and create as
    // many items as needed to fill the empty space.
    function addItemsIfNeeded() {
        // Get extremas items y positions.
        const lastItemY = items[items.length - 1].position.y;
        const firstItemY = items[0].position.y;
        const deltaBottom = viewHeight - lastItemY;
        // If there is empty space at bottom...
        if (deltaBottom > gridSize) {
            // ...add items at bottom.
            const itemsNeededCount = Math.floor(deltaBottom / gridSize);
            addItems(itemsNeededCount, lastItemY);
        // If there is empty space at top...
        } else if (firstItemY > gridSize) {
            // ...add items at top.
            const itemsNeededCount = Math.floor(firstItemY / gridSize);
            addItems(itemsNeededCount, firstItemY, true);
        }
    }
    
    // Create given number of items and add them to the begining or the end of the
    // stack.
    function addItems(count, referenceItemY, before) {
        // For each new item...
        for (let i = 1; i <= count; i++) {
            // ...calculate y position...
            const y = before
                ? referenceItemY - i * gridSize
                : referenceItemY + i * gridSize;
            // ...create item...
            const item = createItem(y);
            // ...add it to the stack.
            if (before) {
                items.unshift(item);
            } else {
                items.push(item);
            }
        }
    }