PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Tuesday, July 26, 2022

[FIXED] When image is cropped, the new image gets the canvas padding fabric js

 July 26, 2022     canvas, crop, fabricjs, javascript     No comments   

Issue

Link to github repository
https://github.com/alvaropsouza/web-image-editor

The cropping function is working just fine, it crops exactly the area selected. The real problem is when the cropped image is created, somehow it gets the canvas padding, making harder for the user find image borders to zoom, resize etc...

PS: Set the new image padding to zero won't work... Also when i try to change it's width and height function the crop don't work properly, like it's getting the wrong selection

Crop function script

var lastSelectedPicture = null;
var isInsertingCropRectangle = false;


var crop_rect, isDown, origX, origY, mask, target;
var done = false;

// IMAGEM DE PLANO DE FUNDO
var src = "https://i.imgur.com/nnCUr4g.jpg";
fabric.Image.fromURL(src, function(img) {
  img.dirty = true;
  img.selectable = false;
  canvas.add(img);
  canvas.renderAll();

canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
  scaleX: canvas.width / img.width,
  scaleY: canvas.height / img.height
})
});

// IMAGEM A SER RECORTADA
fabric.Image.fromURL(src, function(img) {
  img.selectable = true;
  img.id = 'target';
  img.borderColor = 'red'
  
  img.scaleX = canvas.width / img.width
  img.scaleY = canvas.height / img.height
  img.objectCaching = true,
  img.statefullCache = true,
  canvas.add(img);
  canvas.renderAll();
})

canvas.on('object:added', function(e) {
  target = null;
  mask = null;
  canvas.forEachObject(function(obj) {
    //alert(obj.get('id'));
    var id = obj.get('id');
    if (id === 'target') {
      target = obj;
       canvas.setActiveObject(obj);
   }
    if (id === 'mask') {
      //alert(done);
      //alert('mask');
      mask = obj;
    }
  });
});

canvas.on('object:modified', function(e) {
  e.target.setCoords();
  canvas.renderAll();
});

//////////////////////////////////////////////////////////
// MASK
//////////////////////////////////////////////////////////
document.getElementById("mask").addEventListener("click", function() {
    isInsertingCropRectangle = true;
        canvas.discardActiveObject();
        lastSelectedPicture.selectable = false;
        lastSelectedPicture.setCoords();
        lastSelectedPicture.dirty = true;
        canvas.renderAll();
        canvas.discardActiveObject();
        isInsertingCropRectangle = true;
});

//////////////////////////////////////////////////////////
// CROP
//////////////////////////////////////////////////////////
document.getElementById("crop").addEventListener("click", function() {
  if (target !== null && mask !== null) {
    console.log(mask, '01')
    console.log(crop_rect, '02')
        // Re-scale mask
    mask = rescaleMask(target, mask);
    mask.setCoords();
    // Do the crop
    target.clipPath = mask;
    
    target.dirty=true;
    canvas.setActiveObject(target);
    canvas.bringToFront(target);
    target.selectable = true;
    canvas.remove(mask)
    canvas.renderAll();
  }
});

//////////////////////////////////////////////////////////
// RE-SCALE MASK FOR CROPPING
//////////////////////////////////////////////////////////
function rescaleMask(target, mask){
  mask.scaleX = 1;
  mask.scaleY = 1;

  mask.scaleX/=target.scaleX;
  mask.scaleY/=target.scaleY;
 
  var targetCenterX = target.width * target.scaleX / 2;
    var targetCenterY = target.height * target.scaleY / 2;

  var maskOverlapX = mask.left  - target.left;
  var maskOverlapY = mask.top - target.top;
    var centerBasedX = maskOverlapX - targetCenterX;
    var centerBasedY = maskOverlapY - targetCenterY;

  if( maskOverlapX >= targetCenterX){
    centerBasedX = (maskOverlapX - targetCenterX)/target.scaleX;
  }
  else{
 
    centerBasedX = (-(targetCenterX) + maskOverlapX)/target.scaleX;
  }

  if( maskOverlapY >= targetCenterY){
    centerBasedY = (maskOverlapY - targetCenterY)/target.scaleY;
  }
  else{
    centerBasedY = (-(targetCenterY) + maskOverlapY)/target.scaleY;
  }

  mask.left = centerBasedX;
  mask.top = centerBasedY;
  mask.originX = 'left';
  mask.originY = 'top';
  mask.setCoords();
  mask.dirty=true;
  canvas.renderAll();
  
  //var newMask = mask;
  return mask;
}

canvas.on('mouse:down', function(o) {
    if( isInsertingCropRectangle == true ){
    if (done) {
      canvas.renderAll();
      return;
    }
    isDown = true;
    var pointer = canvas.getPointer(o.e);
    origX = pointer.x;
    origY = pointer.y;
    crop_rect = new fabric.Rect({
      left: origX,
      top: origY,
      width: pointer.x - origX,
      height: pointer.y - origY,
      opacity: .3,
      transparentCorners: false,
      selectable: true,
      id: 'mask',
      borderColor: 'red'
    });
    canvas.add(crop_rect);
    canvas.renderAll();
  }
});

canvas.on('mouse:move', function(o) {
    if( isInsertingCropRectangle == true ){
    if (done) {
      canvas.renderAll();
      return;
    }
    if (!isDown) return;
    var pointer = canvas.getPointer(o.e);

    if (origX > pointer.x) {
      crop_rect.set({
        left: Math.abs(pointer.x)
      });
    }
    if (origY > pointer.y) {
      crop_rect.set({
        top: Math.abs(pointer.y)
      });
    }

    crop_rect.set({
      width: Math.abs(origX - pointer.x)
    });
    crop_rect.set({
      height: Math.abs(origY - pointer.y)
    });


    crop_rect.setCoords();
    canvas.renderAll();
  }
  else{
  
  }
});

canvas.on('mouse:up', function(o) {
    if( isInsertingCropRectangle == true ){
    if (done) {
      canvas.renderAll();
      return;
    }
    isDown = false;

    crop_rect.set({
      selectable: true
    });
    done = true;
  }
  else{
  
  }
});

    canvas.on('selection:created', function(event) {
        selectionChanged(event);
  });
    
    canvas.on('selection:updated', function(event) {
        selectionChanged(event);
    });

    function selectionChanged(event){
    switch(event.target.type) {
      case 'textbox':
        break;
        case 'image':
          lastSelectedPicture = event.target;
                break;
            case 'rect':
                break;
            case 'group':
                break;
            default:
                break;
        }
        
    }

Solution

You are currently using clipPaths to crop your image which always keep the dimensions of the original object, not the dimensions of the clipPath (see http://fabricjs.com/clippath-part1). Try using the image properties width, height, cropX, and cropY to achieve your cropping effect instead which will make the image's bounding box have the correct dimensions.

img.set({ width:100, height:100, cropX: 50, cropY: 50 });


Answered By - melchiar
Answer Checked By - Dawn Plyler (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing