Set object drag limit in Fabric.js

2019-01-31 14:30发布

问题:

i am new in fabric js want to set the drag limit

i have also try with https://github.com/kangax/fabric.js/wiki/Working-with-events

not able to get the solution.

please check the attached image, object can move anyware but it should be display in red area only.i want this. help me...thanks in advance !!

回答1:

What had worked for me is to create an event listener for the object:moving event. When the move is happening you update the goodtop and goodleft variables and once you are out of bounds to reposition the object to the last good points.

var goodtop, goodleft, boundingObject;

canvas.on("object:moving", function(){
    var obj = this.relatedTarget;
    var bounds = boundingObject;
    obj.setCoords();
    if(!obj.isContainedWithinObject(bounds)){
        obj.setTop(goodtop);
        obj.setLeft(goodleft);
        canvas.refresh();    
    } else {
        goodtop = obj.top;
        goodleft = obj.left;
    }  
});


回答2:

While Orangepill's answer is correct, it produces a "stuttering" when your object hits the object bounds. If you have a rectangular bounding box (and not a complex bounding object) an alternative is to allow the object to be dragged along the bounds and "slide" along the bounding box. You do this by capping the coordinates values and letting the other dimension move as usual. An example snippet would look like so:

var canvas = new fabric.Canvas("bounded");

var boundingBox = new fabric.Rect({
  fill: "none",
  width: 600,
  height: 400,
  hasBorders: false,
  hasControls: false,
  lockMovementX: true,
  lockMovementY: true,
  evented: false,
  stroke: "red"
});

var movingBox = new fabric.Rect({
  width: 100,
  height: 100,
  hasBorders: false,
  hasControls: false
});

canvas.on("object:moving", function() {
  var top = movingBox.top;
  var bottom = top + movingBox.height;
  var left = movingBox.left;
  var right = left + movingBox.width;

  var topBound = boundingBox.top;
  var bottomBound = topBound + boundingBox.height;
  var leftBound = boundingBox.left;
  var rightBound = leftBound + boundingBox.width;

  // capping logic here
  movingBox.setLeft(Math.min(Math.max(left, leftBound), rightBound - movingBox.width));
  movingBox.setTop(Math.min(Math.max(top, topBound), bottomBound - movingBox.height));
});

canvas.add(boundingBox);
canvas.add(movingBox);

See this example in JSFiddle here



回答3:

Felix Fung's answer was a starting point, but there are many things to consider. Here is a version that accounts for some of them.

It handles the canvas having a viewport transform (ie, zoomed/panned) and objects that are center-origined instead of left/top-origined. It also constrains objects wider/taller than the viewport to the top/left instead of the bottom/right.

canvas.on("object:moving", function(e) {
  var obj = e.target;
  var canvas = obj.canvas;
  var top = obj.top;
  var left = obj.left;
  var zoom = canvas.getZoom();
  var pan_x = canvas.viewportTransform[4];
  var pan_y = canvas.viewportTransform[5];

  // width & height we are constraining to must be calculated by applying the inverse of the current viewportTransform
  var c_width = canvas.width / zoom;
  var c_height = canvas.height / zoom;


  var w = obj.width * obj.scaleX
  var left_adjust, right_adjust
  if(obj.originX == "center") {
    left_adjust = right_adjust = w / 2;
  } else {
    left_adjust = 0;
    right_adjust = w;
  }

  var h = obj.height * obj.scaleY;
  var top_adjust, bottom_adjust;
  if(obj.originY == "center") {
    top_adjust = bottom_adjust = h / 2;
  } else {
    top_adjust = 0;
    bottom_adjust = h;
  }

  // if you need margins set them here
  var top_margin = 0;
  var bottom_margin = 0;
  var left_margin = 0;
  var right_margin = 0;


  var top_bound = top_margin + top_adjust - pan_y;
  var bottom_bound = c_height - bottom_adjust - bottom_margin - pan_y;
  var left_bound = left_margin + left_adjust - pan_x;
  var right_bound = c_width - right_adjust - right_margin - pan_x;

  if( w > c_width ) {
    obj.setLeft(left_bound);
  } else {
    obj.setLeft(Math.min(Math.max(left, left_bound), right_bound));          
  }

  if( h > c_height ) {
    obj.setTop(top_bound);
  } else {
    obj.setTop(Math.min(Math.max(top, top_bound), bottom_bound));          
  }
});


回答4:

SEE THE WORKING EXAMPLE It's as simple as a water try this

just use this js

<script type="text/javascript">
   //use global variable for canvas object


  var canvas;
  var ctx;
 function onLoad() {
  //get fabric canvas with id mycanvas


   canvas = new fabric.Canvas('mycanvas');


   canvas.on("mouse : down",function{

   //get canvas 2d context
   ctx = canvas.getContext("2d");

   ctx.beginPath();
   ctx.rect(115,60,221,390);//specify bounded rectangle
   ctx.closePath();
   ctx.clip();
   ctx.save();
  });
    //now restore the context on mouse up

    canvas.on("mouse : up",function(){
         ctx.restore();//restore the context
    });
}



 </script>

Hope this will help you. Njoy coding :) now u can have the same clipping region for every object supported by Fabric.js for transformation and moving. try it :).



标签: fabricjs