Search code examples
draggablemaskkineticjsclipping

complex clipping boundary in kinetic.js with draggable image


Check out my html5 based clipping constraint on

http://shedlimited.debrucellc.com/test3/canvaskinclip.html

(messing with jsfiddle on http://jsfiddle.net/aqaP7/4/)

So, in html5 I can easily draw a shaped boundary like the following:

         context.beginPath();
  context.moveTo(5, 5);
  context.lineTo(34, 202);

  context.lineTo(2, 405);
  context.lineTo(212, 385);
  context.lineTo(425, 405);
  context.lineTo(400, 202);
  context.lineTo(415, 10);
  context.lineTo(212, 25);
                context.clip();

In kinetic.js though, all I see for clipping options is: height, width, and x, y,

I came across the following : Mask/Clip an Image using a Polygon in KineticJS, but the inner/fill image can't be set to draggable

any help please!


Solution

  • In the new kineticJS versions, a lot of the work is done in the background for you.

    Take a look at this tutorial:

    This fiddle gets you pretty close, here's the code:

     <body>
        <div id="container"></div>
        <script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.0-beta2.js"></script>
        <script>
          function loadImages(sources, callback) {
            var images = {};
            var loadedImages = 0;
            var numImages = 0;
            // get num of sources
            for(var src in sources) {
              numImages++;
            }
            for(var src in sources) {
              images[src] = new Image();
              images[src].onload = function() {
                if(++loadedImages >= numImages) {
                  callback(images);
                }
              };
              images[src].src = sources[src];
            }
          }
          function draw(images) {
            var stage = new Kinetic.Stage({
              container: 'container',
              width: 600,
              height: 700
            });
            var layer = new Kinetic.Layer();
    
            var patternPentagon = new Kinetic.RegularPolygon({
              x: 220,
              y: stage.getHeight() / 4,
              sides: 5,
              radius: 70,
              fillPatternImage: images.yoda,
              fillPatternOffset: [-220, 70],
              stroke: 'black',
              strokeWidth: 4,
              draggable: true
            });
    
    
            patternPentagon.on('dragmove', function() {
            //this.setFillPatternImage(images.yoda);
              //this.setFillPatternOffset(-100, 70);
              var userPos = stage.getUserPosition();
              this.setFillPatternOffset(-userPos.x,-userPos.y);
              layer.draw();
                this.setX(220);
                this.setY(stage.getHeight() / 4);
            });
    
    
            layer.add(patternPentagon);
    
            stage.add(layer);
          }
          var sources = {
            darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg',
            yoda: 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg'
          };
    
          loadImages(sources, function(images) {
            draw(images);
          });
    
        </script>
      </body>
    

    There is a more complex/accurate way of doing this without making it a background pattern, like with grouping objects together