Search code examples
jquerycanvaskineticjs

Kineticjs custom shape cliping/masking image & animating clipped area


I have created a image using kinetic function & used clip: property to do the masking but i can only use rectangular shapes here (no custom shapes allowed).

So i created a custom shape instead and used fillPatternImage: property to place the images inside the shape then i wanted to animate it but turns out if i move the shape image position moves with it.

What i want to achieve: I want the image to stay where it is & animate the clipping area to surf over the still image.

DEMO

CODE:

HTML:

<div id="canvas"></div>
<div class="animate">Animate this</div>

CSS:

#canvas {
    width: 600px;
    height: 600px;
}
.animate {
    cursor: pointer;
}

JS:

$(function () {
    stage = new Kinetic.Stage({
        container: 'canvas',
        width: 600,
        height: 600
    });

    var layer = new Kinetic.Layer();

    // Image
    imageObj = new Image();
    imageObj.src = 'https://avatars3.githubusercontent.com/u/1498774?s=460';

    // Mask
    poly = new Kinetic.Line({
        points: [0, 0, 100, 50, 200, 150, 50, 200],
        fillPatternImage: imageObj,
        stroke: 'black',
        strokeWidth: 0,
        name: 'poly',
        closed: true,
    });

    layer.add(poly);
    stage.add(layer);

    i = 0;
    valueX = 1;
    animationLoop();

    $(".animate").click(function () {
        i = 0;
        animationLoop();
    });
});


function animationLoop() {
    if (i < 50) {
        setTimeout(function () {
            animateThis();
        }, 100);
    }
}

function animateThis() {
    poly.setX(valueX);
    valueX += 1;
    i += 1;
    stage.draw();
    animationLoop();
}

stage.draw();

Solution

  • DEMO

    Well what can be done is: simply move the image in opposite direction to give the feel that only the shape is moving and image is still.

    fillPatternOffset property can be used to do this.

    CODE: (HTML & CSS are same)

    JS:

    $(function(){
    stage = new Kinetic.Stage({
        container: 'canvas',
        width: 600,
        height: 600
    });
    
    var layer = new Kinetic.Layer();
    
    // Image
    imageObj = new Image();
    imageObj.src = 'https://avatars3.githubusercontent.com/u/1498774?s=460';
    
    // Mask
    poly = new Kinetic.Line({
        points: [0, 0, 100, 50, 200, 150, 50, 200],
        fillPatternImage: imageObj,
        stroke: 'black',
        strokeWidth: 0,
        fillPatternOffset: [10,10],
        name: 'poly',
        closed: true,
    });
    
    layer.add(poly);
    stage.add(layer);
    
    i = 0;
    valueX = 1; 
    animationLoop();
    
        $(".animate").click(function(){
            i = 0;
            animationLoop();
        });
    });
    
    
    function animationLoop(){
        if(i<50){
            setTimeout(function(){
              animateThis();
            }, 100);
        }
    }
    function animateThis(){
        poly.fillPatternOffsetX(valueX);
        poly.fillPatternOffsetY(valueX);
        poly.setX(valueX);
        poly.setY(valueX);
        valueX += 1;
        i += 1;
        stage.draw();
        animationLoop();
    }
    
    stage.draw();