0

edit 2016, Oct 24

I've an idea about this feature by using 'pattern' which seems to be a good idea.

I tried to prove my thoughts with this pen, its still buggy but at least we can set the image(pattern) position and keep the original image when double click.

I'am not very good at javascript, So if you are interest in this please help to make this more useable, any discussions/thoughts or code correction is welcome. http://codepen.io/wushan/pen/LRrQEL?editors=1010

// Create Canvas
var canvas = this.__canvas = new fabric.CanvasEx('c', {
  preserveObjectStacking: true
});
fabric.Object.prototype.transparentCorners = false;
// Global Settings
var url = "http://fabricjs.com/assets/pug.jpg";

//Make the Pattern by url
function createMaskedImage(url) {
  //Load Image
  fabric.Image.fromURL(url, function(img) {
    img.scaleToWidth(300);
    //Make a Pattern
    var patternSourceCanvas = new fabric.StaticCanvas();
    patternSourceCanvas.add(img);

    var pattern = new fabric.Pattern({
      source: function() {
        patternSourceCanvas.setDimensions({
          width: img.getWidth(),
          height: img.getHeight()
        });
        return patternSourceCanvas.getElement();
      },
      repeat: 'no-repeat'
    });
    console.log(pattern.offsetX)
    console.log(pattern.offsetY)
    console.log(img.getWidth()) // 縮小後 (*scale)
    console.log(img.width) // 原尺寸
    
    //Mask (can be any shape ex: Polygon, Circles....)
    var rect = new fabric.Rect({
      width: 200,
      height: 200,
      left: 150,
      top: 100,
      fill: pattern
    })
    
    //Bind Double Click Event from fabric.ext
    //https://github.com/mazong1123/fabric.ext
    rect.on('object:dblclick', function (options) {
      //Pass pattern out
      enterEditMode(rect, img);
    });
    canvas.add(rect);
    canvas.setActiveObject(rect);
  }); 
}

function enterEditMode(mask, image) {
  image.left = mask.left;
  image.top = mask.top;
  // New Image
  // Fake Crop Area (fixed)
  var rect = new fabric.Rect({
      width: mask.width,
      height: mask.height,
      left: mask.left,
      top: mask.top,
      fill: '#000000',
      opacity: 0.8,
      selectable: false
    })
  canvas.remove(mask);
  canvas.add(image);
  image.on('object:dblclick', function (options) {
      //Flatten
      flatten(rect, image);
  });
  canvas.add(rect);
  // console.log(JSON.stringify(canvas));
}

function flatten(mask, image) {
  //Make a Pattern
  var patternSourceCanvas = new fabric.StaticCanvas();
  patternSourceCanvas.add(image);

  var pattern = new fabric.Pattern({
    source: function() {
      patternSourceCanvas.setDimensions({
        width: image.getWidth(),
        height: image.getHeight()
      });
      return patternSourceCanvas.getElement();
    },
    repeat: 'no-repeat'
  });

  //Offsets
  pattern.offsetX = image.left - mask.left - image.left;
  pattern.offsetY = image.top - mask.top - image.top;
  
  var rect = new fabric.Rect({
    width: mask.width,
    height: mask.height,
    left: mask.left,
    top: mask.top,
    fill: pattern
  })

  //Bind Double Click Event from fabric.ext
  //https://github.com/mazong1123/fabric.ext
  rect.on('object:dblclick', function (options) {
    //Pass pattern out
    enterEditMode(rect, image);
  });
  canvas.remove(mask);
  canvas.remove(image);
  canvas.add(rect);
  canvas.setActiveObject(rect);
  canvas.renderAll();
}

//Button Events
//Create
document.getElementById('createMaskedImage').addEventListener('click', function () {
  createMaskedImage(url);
});

Test this :

  1. click 'create'
  2. double click on the image object
  3. move/scale the image
  4. double click the image to flatten the obejct.

Know issue:

  1. when cutting the image without scale, the image position looks correct but there is a wired transparent space.

enter image description here

enter image description here

enter image description here

  1. It generates a lot duplicate objects on the scene... enter image description here

Original Post

I've been working with fabric.js for a few month, haven't seen any example or discussions about a mask/crop system which is behaves like canva.com ( which is way easy to understand for users. )

the object looks like this:

enter image description here

when double clicked on a group/mask, it shows the original image with an unselectable mask, you can move/scale the image whatever you need and click 'OK' to made the change without modifying the original image.

enter image description here

I'd like to know if there is any possible solutions about making this in fabricjs, or maybe some thoughts about this issue is welcome.

Thank you a lot !

Community
  • 1
  • 1
wushan
  • 55
  • 2
  • 7
  • Stack overflow has mask and crop answers for native canvas. Use those answers and then use the native as an image source for a fabric image – markE Oct 08 '16 at 17:55
  • can you provide some directions to find those native solutions ? I can't find any. thank you. – wushan Oct 09 '16 at 06:00
  • Here are several [Q&A](http://stackoverflow.com/questions/38568032/how-to-crop-a-selected-rectangle-using-based-on-mouse-clicks/38575252#38575252) & [Q&A](http://stackoverflow.com/questions/27213413/canvas-cropping-images-in-different-shapes/27217902#27217902) for you to start with. Add your desired design to the basic procedure. – markE Oct 09 '16 at 19:19

0 Answers0