在Fabric.js中使用setAngle()后,旋转和缩放控件关闭

时间:2014-04-22 21:15:32

标签: canvas rotation fabricjs

我想让用户在Fabric.js动力画布上旋转对象,但将其旋转限制为90度增量。想法是,当它们旋转然后停止时,物体将以最接近的角度“捕捉”到位。

这可以通过听“object:rotating”,设置最近的角度,然后调用object.setAngle(angleClosestTo90)来正常工作。但是,一旦对象被“捕捉”,缩放/旋转图像的控件就会关闭。你仍然可以选择它们,但它很挑剔 - 我想这个对象应该是它的最后一个位置,而不是通过setAngle()重新计算的那个。

This JSFiddle演示了这个问题:

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

var rect = new fabric.Rect({
  left: 100,
  top: 100,
  fill: 'red',
  width: 90,
  height: 90
});

canvas.add(rect);
canvas.renderAll();

var lastClosestAngle = 0,
    snapAfterRotate = false;

function calculateClosestAngle(targetObj) {
  // if angle > 360 then mod 360
  var currentAngle = targetObj.angle;
  var normalizedAngle = Math.abs(Math.round(Math.asin(Math.sin(currentAngle * Math.PI/360.0)) * 360.0/Math.PI));
  console.log("normalized: ", normalizedAngle);
  snapAfterRotate = true;
  if (normalizedAngle >= 45 && normalizedAngle < 135) {
    return 90;
  } else if (normalizedAngle >= 135 && normalizedAngle < 225) {
    return 180;
  } else if (normalizedAngle >= 225 && normalizedAngle < 315) {
    return 270;
  } else if ((normalizedAngle >= 315 && normalizedAngle <= 360) || (normalizedAngle >= 0 && normalizedAngle < 45)) {
    return 0;
  }
  return currentAngle;
}

canvas.on("object:rotating", function(rotEvtData) {
  var targetObj = rotEvtData.target;
  lastClosestAngle = calculateClosestAngle(targetObj);
});

canvas.on("object:modified", function(modEvtData) {
  // modified fires after object has been rotated 
  var modifiedObj = modEvtData.target;
  if (modifiedObj.angle && snapAfterRotate) {
      modifiedObj.setAngle(lastClosestAngle);
      snapAfterRotate = false;
      canvas.renderAll();
  }
})

旋转盒子,然后松开鼠标。将选择该对象,但尝试再次旋转它。指针很难找到/不可用。

如果你点击远离物体,然后重新选择(或只是在旋转后移动物体),它就可以了。

2 个答案:

答案 0 :(得分:6)

在setAngle()之后运行setCoords()。这将更新控件的位置。在你的小提琴里尝试过。工作正常。

   canvas.on("object:modified", function(modEvtData) {
     // modified fires after object has been rotated 
     var modifiedObj = modEvtData.target;
     if (modifiedObj.angle && snapAfterRotate) {
         modifiedObj.setAngle(lastClosestAngle).setCoords();
         snapAfterRotate = false;
         canvas.renderAll();
     }
   })

的问候, 贝尼克

答案 1 :(得分:2)

FabricJS现在通过'setAngle'以及'snapThreshold'属性本地支持它。

https://github.com/kangax/fabric.js/pull/3383

示例:

canvas.add(new fabric.Circle({
  snapAngle: 90,
  snapThreshold: 45,
  left: 100, 
  top: 100, 
  radius:50,
  fill: '#9f9', 
  centeredRotation: true
}));

https://jsfiddle.net/2t2d1zj9/1/

enter image description here