当 canvas 响应时,拖动不会检测到掉落

Drag doesn't detect drop when the canvas is made responsive

在 Animate CC 中,使用 CreateJS/EaselJS API,我创建了大量不同的 HTML5 canvas,所有这些都具有拖放元素,每次都具有渐进的功能。

为了构建拖放交互,我在 mousedownpressmovepressup 事件上向 Drag MovieClip 添加了一些 EventListeners。它们都有相关的功能。

拖动 MovieClip 的(部分)动作代码

/* this refers to the Drag MovieClip */ 
root = this;

/* Mousedown Events */

/* removingFromDrop: Detects when a Drag is removed from certain Drop */
root.on("mousedown", removingFromDrop);

/* Pressmove Events */ 

/* onPressMove: Moves the Drag on pressmove */ 
root.on("pressmove", onPressMove);

/* detectDrop: While pressmoving, detects if the Drag is over a Drop */ 
root.on("pressmove", detectDrop); 

/* Pressup events */

/* setDragOverDrop: Releasing the left button of the mouse, 
   if a Drag is over a Drop, the Drag is positioned over the Drop */ 
root.on("pressup", setDragOverDrop); 

正如我所说,所有的拖放功能都是以渐进的方式实现的,因此在某些 canvas 中,拖动不会检测到拖放(有意),在其他情况下,透明度(alpha)是当它们在一滴上方时应用于拖动,在其他情况下,必须将拖动放在一滴上方或 return 到它们的原始位置,在其他情况下,当将拖动放在一滴上方时,它不能被拖放到其他职位;等等

几乎所有这些实现中没有改变的是拖动在 pressmove 事件上移动的方式...

onPressMove 函数

function onPressMove(event) {
    // There is more code here, but for effects 
    // of this question, it's irrelevant

    /* In layer terms, drag must be over the drop  */ 
    root.parent.setChildIndex(event.currentTarget, root.parent.numChildren-1);

    /* Drag takes the actual position of the mouse pointer  */ 
    var point = stage.globalToLocal(event.stageX, event.stageY); 
    event.currentTarget.x = point.x;
    event.currentTarget.y = point.y; 
}

...以及它如何在低于 pressmove 事件时检测到跌落。

detectDrop 函数

function detectDrop(event){
    /* The original function is more complex than this. For example, the drop detection 
       in the original function is being done against all the available drops. 
       For effects of this question, I'm simplyfying this function, doing the detection 
       over a single drop */

    /* Initial variables */
    var dropLocation;       //  Drop Location
    var point;              //  Point for the collision comparison
    var dropFound = false;  //  Drop is found? By default, no. 

    /* Drop is cloned. For effects of this question, the drop is a global variable. */
    dropLocation = drop.clone();

    /* Position of the drop is converted to local using the mouse pointer position */   
    point = dropLocation.globalToLocal(event.stageX, event.stageY);

    /* In local coordinates, the drag intersects with the point defined before? */  
    if (event.currentTarget.hitTest(point.x,point.y)) {   
        /* If yes, the drop was found */ 
        dropFound = true;                      
    }

    if (dropFound) {  
        // Irrelevant for effects of this question 
    }
}

只有一种情况是拖放交互没有按预期工作,这种情况是 canvas 响应

当canvas位于中心时没有问题,拖动移动和掉落检测都可以正常工作。

但是当 canvas 变成响应式时,拖动的动作很好,但是 拖动时不会检测到掉落。正如我到目前为止所测试的,拖动检测到某个下降,在另一个位置,这显然不是前面提到的下降的位置。

在我对 drags/drops 进行了一些类似于上面显示的核心实现的测试之后,我得出了一个解决方案,该解决方案涉及对 drop 检测函数.

首先,point 变量现在保存当前鼠标在舞台坐标 space 内的位置:

var point = stage.globalToLocal(event.stageX, event.stageY);

然后,我用那个点变换到下落的坐标space。该转换保存在另一个点变量中:

var pointGTL = dropLocation.globalToLocal(point.x, point.y); 

正在使用之前定义的点变量完成本地坐标中的相交测试:

event.currentTarget.hitTest(pointGTL.x,pointGTL.y) 

现在跌落检测功能如下所示:

detectDrop 函数

function detectDrop(event){
    /* Initial variables */
    var dropLocation;       //  Drop Location
    var point, pointGTL;    //  Points for the collision comparison
    var dropFound = false;  //  Drop is found? By default, no. 

    /* Drop is cloned */
    dropLocation = drop.clone();

    /* Position of the stage is converted to local 
       using the mouse pointer position */  
    point = stage.globalToLocal(event.stageX, event.stageY);

    /* Then, the position of the drop is converted to local 
       using the point defined before */ 
    pointGTL = dropLocation.globalToLocal(point.x, point.y); 

    /* In local coordinates, the drag intersects with the point defined before? */  
    if (event.currentTarget.hitTest(pointGTL.x,pointGTL.y)) {   
        /* If yes, the drop was found */ 
        dropFound = true;                      
    }

    /* Rest of the code */
}

拖动在两种响应模式(适合视图或拉伸以适合)下都可以正常工作。