Search code examples
kineticjs

How to apply masks to rectangle which fill with image object in kineticjs


I have researched many forums and tutorial to find the idea or solution to apply a different shape of masks to the rectangle which fill with image obj in Kinecticjs. But I have tried with different method but failed to achieve the final output.

For example : Please get the image from here http://postimg.org/image/5czqujzxb/

Anyone have idea with this? Thanks for advance for sharing the knowledge and solution.


Solution

  • KineticJS has built in support for rectangular clipping, but not for clipping to a path (like your heart).

    Instead, you can create a custom Kinetic.Shape and use compositing to fill your heart-mask with your pattern.

    Since KineticJS does not have built-in compositing, the trick is to get a reference to the actual html5 canvas context which KineticJS uses for drawing:

    var maskedShape = new Kinetic.Shape({
      x: 20,
      y: 20,
      drawFunc: function(context) {
    
        // ctx is the actual html5 context used by this shape
        var ctx=context.canvas._canvas.getContext('2d');
    
      }
    });
    

    Then you can use html5 context's 'source-in' compositing to restrict your pattern to drawing only into the heart-mask:

    ctx.drawImage(heartMaskImage,0,0);
    ctx.globalCompositeOperation='source-in';
    ctx.drawImage(patternImage,0,0);
    

    Here is a Demo:

    var stage = new Kinetic.Stage({
      container: 'container',
      width: 450,
      height: 450
    });
    var layer = new Kinetic.Layer();
    stage.add(layer);
    
    // put the paths to your images in imageURLs[]
    var imageURLs=[];  
    // push all your image urls!
    imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/mask1.png");
    imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/pattern1.jpg");
    
    // the loaded images will be placed in images[]
    var imgs=[];
    
    var imagesOK=0;
    loadAllImages(start);
    
    function loadAllImages(callback){
      for (var i=0; i<imageURLs.length; i++) {
        var img = new Image();
        imgs.push(img);
        img.onload = function(){ 
          imagesOK++; 
          if (imagesOK>=imageURLs.length ) {
            callback();
          }
        };
        img.onerror=function(){alert("image load failed");} 
        img.crossOrigin="anonymous";
        img.src = imageURLs[i];
      }      
    }
    
    function start(){
    
      // the imgs[] array now holds fully loaded images
      // the imgs[] are in the same order as imageURLs[]
    
      var maskedShape = new Kinetic.Shape({
        x: 20,
        y: 20,
        drawFunc: function(context) {
          var ctx=context.canvas._canvas.getContext('2d');
          ctx.save();
          ctx.drawImage(imgs[0],0,0);
          ctx.globalCompositeOperation='source-in';
          ctx.drawImage(imgs[1],0,0);
          ctx.restore();
        }
      });
      layer.add(maskedShape);
      layer.draw();
    
    }
    body{padding:20px;}
    #container{
    	border:solid 1px #ccc;
      margin-top: 10px;
      width:450px;
      height:450px;
    }
    <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.1.0.min.js"></script>
    <div id="container"></div>