HTML5 Canvas:在画布外拖动

Posted

技术标签:

【中文标题】HTML5 Canvas:在画布外拖动【英文标题】:HTML5 Canvas: Dragging outside of canvas 【发布时间】:2012-12-28 13:57:43 【问题描述】:

我在使用 html5 Canvas 实现拖动功能时遇到问题。我了解缺少场景图等,并设置了一种方法来识别鼠标事件上的拖动矩形。

但是:问题是当鼠标离开画布时会丢失鼠标事件。如果我拖到画布外并释放鼠标按钮,我的代码不会获得 mouseup 事件来相应地改变拖动逻辑。然后,拖动的对象会一直粘在我的鼠标上,直到我再次开始拖动。

fabric.js doesn't have this problem,但是我无法识别库中的相关代码。它是如何做到的?

【问题讨论】:

【参考方案1】:

首先使用布尔变量 isMouseDragged,它在 mouseDown 之后设置为 true,在 mouseUp 之后设置为 false(或者我稍后会解释的另一个事件)

您可以通过多种方式处理拖动。

if (mouse['isMouseDragged']) 
   mouse['xUp'] = e.clientX - canvas.getBoundingClientRect().left;
   mouse['yUp'] = e.clientY - canvas.getBoundingClientRect().top;
   ...

    在鼠标向上计算您按下和释放按钮的点(将其想象为线)与画布边缘之间的交点,鼠标指针超出该点(将其想象为另一条线)。将 mouseUp 位置作为这两条线的交点。

    // FIRST OPTION
    if (mouse['mode'] == mouse['INTERSECTION']) 
        if (!mouse['isMouseOver']) 
            var edgeIntersect = mouseDraggedOut(mouse['xDown'], mouse['yDown'], mouse['xUp'], mouse['yUp']);
            mouse['xUp'] = edgeIntersect['x'];
            mouse['yUp'] = edgeIntersect['y'];
        
    
    

    将虚拟鼠标指针(坐标)放在画布内。

    // SECOND OPTION
    if (!mouse['isMouseOver']) 
        if (mouse['mode'] == mouse['LOCK_INSIDE']) 
            var edgeIntersect = mouseDraggedOut(canvas.width / 2, canvas.height / 2, mouse['x'], mouse['y']);
            mouse['x'] = edgeIntersect['x'];
            mouse['y'] = edgeIntersect['y'];
        
    
    

    在你离开画布时设置 onMouseUp = onMouseOut 坐标并将 isMouseDragged 设置为 false。

    // THIRD OPTION
    if (mouse['isMouseDragged']) 
       if (mouse['mode'] == mouse['MOUSEOUT_POS']) 
          mouse['xUp'] = mouse['xOut'];
          mouse['yUp'] = mouse['yOut'];
          mouse['isMouseDragged'] = false;
       
    
    

计算画布边缘的相交:

function mouseDraggedOut(x1, y1, x2, y2) 
// x1,y1 = mouseDown;  x2,y2 = mouseUp

var x3, y3, x4, y4;
var thisX, thisY;

if (x2 < 0) // left edge
    x3 = 0;
    y3 = 0;
    x4 = 0;
    y4 = canvas.height;
    thisX = Math.round(x1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (x2 - x1));
    thisY = Math.round(y1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (y2 - y1));

    // I must do this for other checks, else corners (when two conditions are true) couldn't be handled
    // So I'll handle it one after another
    x2 = thisX;
    y2 = thisY;


if (x2 > canvas.width - 1) // right edge
    x3 = canvas.width - 1;
    y3 = 0;
    x4 = canvas.width - 1;
    y4 = canvas.height - 1;
    thisX = Math.round(x1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (x2 - x1));
    thisY = Math.round(y1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (y2 - y1));
    x2 = thisX;
    y2 = thisY;


if (y2 < 0) // top edge
    x3 = 0;
    y3 = 0;
    x4 = canvas.width - 1;
    y4 = 0;
    thisX = Math.round(x1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (x2 - x1));
    thisY = Math.round(y1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (y2 - y1));
    x2 = thisX;
    y2 = thisY;


if (y2 > canvas.height - 1) // bottom edge
    x3 = 0;
    y3 = canvas.height - 1;
    x4 = canvas.width - 1;
    y4 = canvas.height - 1;
    thisX = Math.round(x1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (x2 - x1));
    thisY = Math.round(y1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (y2 - y1));


return 
    'x' : thisX,
    'y' : thisY
;

看源码:http://jsfiddle.net/WolfeSVK/s2tNr/

【讨论】:

和这个想法一样,不幸的是小提琴链接已经死了。 我修改了我的答案(错误的文本格式),并且 jsfiddle 链接现在正在工作......【参考方案2】:

解决方案是附加到mouseleave 事件,并且不再将用于拖动的按钮考虑在您的逻辑中。

【讨论】:

以上是关于HTML5 Canvas:在画布外拖动的主要内容,如果未能解决你的问题,请参考以下文章

如何在 HTML5 Canvas 中创建可拖动的线条?

新手用canvas画布画啥比较好

HTML5 中的 canvas 画布

HTML5Canvas画布

如何在 HTML5 画布周围拖动一段用户生成的文本?

教程HTML5 Canvas旋涡粒子动画特效