Search code examples
javascripthtmlkineticjs

KineticJS: Image does not have a Stroke after applying a Filter


Using KineticJS 5.1.0

I have a KineticJS image with a stroke. To this image I want to apply a filter. After caching and applying the filter the stroke has gone.

Here is a JSFiddle and my demo code:

var imageObj = new Image();
      imageObj.onload = function() {
        var stage = new Kinetic.Stage({
          container: 'container',
          width: 600,
          height: 700
        });
        var layer = new Kinetic.Layer();
        img = new Kinetic.Image({
          x: 250,
          y: 200,
          image: imageObj,
          draggable: true
        });
        var strokeWidthValue = 10;
        img.setOffsetX(img.getWidth() / 2); 
        img.setOffsetY(img.getHeight() / 2); 
        img.stroke("green");  
        img.strokeWidth(strokeWidthValue);
        img.strokeScaleEnabled(false);  
        img.strokeEnabled(true);  

        layer.add(img);
        stage.add(layer);

        img.cache();
        img.filters([Kinetic.Filters.Invert]);
        layer.draw();
      };
       imageObj.crossOrigin = "anonymous";
      imageObj.src =
  "https://dl.dropboxusercontent.com/u/47067729/darth-vader.jpg";

Here is the image before I apply the filter:

enter image description here

And here after I apply the filter:

enter image description here

How do I get the stroke back after applying the filter?

Edit: I also tried to add extra space for the border but the result shows a pink border, where my one should be green. Here is the cache function I tried:

    img.cache({
        x: -(img.getWidth() / 2) - strokeWidthValue,
        y: -(img.getHeight() / 2) - strokeWidthValue,
        width: img.getWidth() + (strokeWidthValue * 2),
        height: img.getHeight() + (strokeWidthValue * 2)
    });

here is the result:

enter image description here

The complete example can be found in this JSFiddle.


Solution

  • http://jsfiddle.net/truefusion/o73ur6pf/8/

    When we create a cache and apply a filter to the image, we are able to access the result from Kinetic.Image._cache.canvas.filter. We can then convert the result into a data URI by calling toDataURL() on the filter canvas. In order to avoid issues when clearing the image cache, we create a new image element and assign it the data URI to its src attribute. Then we set the new image to the Kinetic image object using img.setImage().

    var image = new Image()
    ,   data  = img._cache.canvas.filter.toDataURL()
    ;
    
    image.src = data;
    img.setImage(image);
    

    You can then safely clear the cache, pass null to unload callback, and have fun!

    You have to account for the size of the stroke. In other words, in the img.cache() properties, subtract strokeWidth from X and Y, and add (strokeWidth * 2) to the width and height.