在 Fabric.js 中使用 setAngle() 后,旋转和缩放控件关闭 [英] Rotation and Scaling controls are off after using setAngle() in Fabric.js

查看:105
本文介绍了在 Fabric.js 中使用 setAngle() 后,旋转和缩放控件关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让用户在 Fabric.js 驱动的画布上旋转对象,但将它们的旋转限制为 90 度增量.想法是,当它们旋转然后停止时,对象会以最近的角度卡入"到位.

I want to let users rotate objects on the Fabric.js powered canvas, but limit their rotation to 90 deg increments. Idea is that as they rotate and then stop, the object would "snap" into place at the closest angle.

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

This works okay by listening to "object:rotating", setting the closest angle, then calling object.setAngle(angleClosestTo90). However, once the object has been "snapped", the controls for scaling/rotating the image are off. You can still select them, but it's finicky - I guess the object is expected to be at it's last location, not the one recalculated via setAngle().

这个 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();
  }
})

旋转盒子,然后放开鼠标.该对象将被选中,但请尝试再次旋转它.指针很难找到/不可用.

Rotate the box, then let go of the mouse. The object will be selected, but try to rotate it again. The pointer is hard to find/unavailable.

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

If you click away from the object, then reselect (or just move the object after rotating), it is fine.

推荐答案

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

Run setCoords() after setAngle(). This will update the position of the controls. Tried it in your fiddle. Works fine.

   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();
     }
   })

问候,贝尼克

这篇关于在 Fabric.js 中使用 setAngle() 后,旋转和缩放控件关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆