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

Canvas 在Fabric.js中使用setAngle()后,旋转和缩放控件将关闭,canvas,rotation,fabricjs,Canvas,Rotation,Fabricjs,我想让用户在电动画布上旋转对象,但将其旋转限制为90度增量。这个想法是,当它们旋转然后停止时,对象将以最接近的角度“捕捉”到位 通过听“object:rotating”,设置最接近的角度,然后调用object.setAngle(angleClosestTo90),可以正常工作。但是,一旦对象被“捕捉”,用于缩放/旋转图像的控件将关闭。您仍然可以选择它们,但这很挑剔-我猜对象应该位于它的最后一个位置,而不是通过setAngle()重新计算的位置 说明问题: var canvas = new fab

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

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

说明问题:

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();
  }
})
var canvas=newfabric.canvas(“c”);
var rect=new fabric.rect({
左:100,,
前100名,
填充:“红色”,
宽度:90,
身高:90
});
canvas.add(rect);
canvas.renderAll();
var lastClosestAngle=0,
snapAfterRotate=false;
函数calculateClosestAngle(targetObj){
//如果角度>360,则为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));
log(“normalized:”,normalizedAngle);
snapAfterRotate=true;
if(normalizedAngle>=45&&normalizedAngle<135){
返回90;
}否则如果(normalizedAngle>=135&&normalizedAngle<225){
返回180;
}否则如果(normalizedAngle>=225&&normalizedAngle<315){
返回270;
}否则如果((normalizedAngle>=315&&normalizedAngle=0&&normalizedAngle<45)){
返回0;
}
回流角;
}
canvas.on(“对象:旋转”,函数(RotVTData){
var targetObj=rotEvtData.target;
lastClosestAngle=calculateClosestAngle(targetObj);
});
canvas.on(“对象:已修改”,函数(modEvtData){
//已修改的在对象旋转后激发
var modifiedObj=modEvtData.target;
if(修改后的角度和捕捉后旋转){
修改后的设定角度(lastClosestAngle);
snapAfterRotate=false;
canvas.renderAll();
}
})
旋转盒子,然后放开鼠标。将选择该对象,但请再次尝试旋转它。指针很难找到/不可用

如果单击远离对象,然后重新选择(或旋转后仅移动对象),则可以

在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();
     }
   })
问候,, Benick

在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();
     }
   })
问候,,
Benick

FabricJS现在通过“设置角度”以及“snapThreshold”属性以本机方式支持此功能

例如:

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


FabricJS现在通过“setAngle”以及“snapThreshold”属性本机支持此功能

例如:

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


太棒了。我想我只需要“刷新”对象,并尝试通过API选择/取消选择它,但没有成功。非常感谢!令人惊叹的我想我只需要“刷新”对象,并尝试通过API选择/取消选择它,但没有成功。非常感谢!还有一种方法与
calculateClosestAngle
相同,也有一种方法与
calculateClosestAngle
相同,而不是将链接发布为答案。添加一些文本来解释此答案如何帮助OP解决当前问题。感谢注意:这仅适用于通过控制手柄进行的旋转。如果您使用结构手势库通过挤压进行旋转,则无法识别捕捉。请添加一些文字来解释此答案如何帮助操作解决当前问题,而不是将链接作为答案发布。ThanksNote:这仅适用于通过控制手柄进行旋转。如果使用构造手势库通过挤压进行旋转,则无法识别捕捉。