【问题标题】:Fabric.js - Move object without holding mouse buttonFabric.js - 在不按住鼠标按钮的情况下移动对象
【发布时间】:2016-01-27 01:56:04
【问题描述】:

在 Fabric.js 中,可以通过左键单击、按住和移动鼠标在画布中移动对象。在这种情况下,选定对象跟随鼠标光标,object:moving 被触发。释放鼠标左键退出此模式。

有没有办法改变这种行为并让对象通过不同的事件进入这种模式?例如,单击一次以使对象跟随光标(并使object:moving 正确触发),然后再次单击以将对象释放到其最终位置?

我希望避免从头开始编写这个监听“鼠标移动”事件,因为这已经实现,但只有进入/存在这个模式的触发器必须改变。

【问题讨论】:

    标签: javascript fabricjs


    【解决方案1】:

    通过Fabric.js代码,一个对象被标记为移动的地方是在canvas.__on_mouse_down(e)中,它调用了canvas._setupCurrentTransform(e, target)(仅使用该方法的地方)。这会构造一个对象并将其分配给canvas._currentTransform。而这个对象又在canvas.__onMouseMove(e) 中使用,以使用canvas._transformObject(e) 实际移动选定的对象。

    问题是canvas.__onMouseUp(e) 调用canvas._finalizeCurrentTransform(),所以拖到那里就停止了。幸运的是,它也会在之后立即触发“mouse:up”。所以我们可以在回调中覆盖它:

    var mydragging = false;
    canvas.on('mouse:up', function(o) {
      if (mydragging) {
        mydragging = false;
        canvas.currentTransform = null;
      }
      else {
        canvas._setupCurrentTransform(o.e, o.target);
        mydragging = true;
      }
    });
    

    这会将canvas 置于与按住鼠标按钮拖动时完全相同的状态(在引入此代码之前),因此所有内置行为都保持不变,包括触发“object:moving”。

    很遗憾,canvas._currentTransformcanvas._setupCurrentTransform 被标记为私有,无法依赖。也许他们愿意公开。

    【讨论】:

    【解决方案2】:

    我通过使用一个名为movedObject 的变量来实现这一点,如果没有移动对象,则该变量为null,如果移动了对象,则包含一个对象。如果在移动对象时单击,则会将movedObject 设置为null。如果您在不移动对象的情况下单击,那么它会将movedObject 设置为如果您单击了一个对象。

    我向mouse:move 添加了一个侦听器,它将movedObjectmovedObjecttop 设置为鼠标xy(减去movedObject widthheight / 2)如果 movedObject 不是null

    JSFiddle

    代码:

    var canvas = new fabric.Canvas('canvas');
    canvas.setWidth(300);
    canvas.setHeight(300);
    var circle = new fabric.Circle({
      radius: 30,
      fill: '#f55',
      top: 100,
      left: 100
    });
    canvas.add(circle);
    circle.hasControls = circle.hasBorders = circle.selectable = false;
    
    var movedObject = null;
    canvas.on({
      'mouse:down': function(e) {
        //If an object is selected already it'll be unselected
        if (movedObject !== null) {
            movedObject = null;
        } else {
          //If no object was selected and a click occured on an object it'll now be selected
          if (e.target) {
             movedObject = e.target;
          }
        }
      },
      'mouse:move': function(e) {
        //Moving the object along with mouse cursor
        if (movedObject !== null) {
            movedObject.left = (e.e.clientX - movedObject.width / 2);
            movedObject.top = (e.e.clientY - movedObject.height / 2);
            movedObject.setCoords();
            canvas.renderAll();
        }
      }
    });
    

    【讨论】:

    • 这正是我试图避免的。这重新实现了 fabric.js 中已经存在的大部分内容,增加了开销并且不能很好地与事件系统配合使用。
    • 这可能是不修改fabric.js中代码的唯一方法。我会给你的(因此我赞成)。但这不是问题的答案,这在问题中已明确说明。为了进一步澄清,这不会触发“object:moving”事件,例如,您必须手动触发它,从而继续复制代码,增加开销并使其难以维护。
    猜你喜欢
    • 2021-09-03
    • 1970-01-01
    • 2020-03-18
    • 1970-01-01
    • 2019-07-29
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    相关资源
    最近更新 更多