我想让用户在Fabric.js动力画布上旋转对象,但将其旋转限制为90度增量.想法是,当它们旋转然后停止时,物体将以最接近的角度"咬合"到位.
通过监听"object:rotating",设置最近的角度,然后调用object.setAngle(angleClosestTo90),这可以正常工作.但是,一旦对象被"捕捉",缩放/旋转图像的控件就会关闭.你仍然可以选择它们,但它很挑剔 - 我想这个对象应该是它的最后一个位置,而不是通过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(); } })
旋转盒子,然后松开鼠标.将选择该对象,但尝试再次旋转它.指针很难找到/不可用.
如果你单击远离对象,然后重新选择(或只是在旋转后移动对象),它没关系.
在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(); } })
问候,贝尼克