且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

HTML5画布:在画布之外拖动

更新时间:2022-11-02 14:45:33

首先使用布尔变量isMouseDragged,在mouseDown后设置为true,在mouseUp我会在稍后解释)



您可以处理拖曳的几种方式。

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




  1. 在你按下和释放按钮的点之间的交叉点(想象它为线)和画布的边缘,超过它是鼠标指针(想象它作为另一条线)。将mouseUp位置作为这两行的交集。

      //第一个选项
    if(mouse ['mode'] =鼠标['xDown'],鼠标['yDown'],鼠标['xDown'],鼠标['XYZ] 'xUp'],mouse ['yUp']);
    mouse ['xUp'] = edgeIntersect ['x'];
    mouse ['yUp'] = edgeIntersect ['y'];保持您的虚拟鼠标指针(坐标),然后单击鼠标左键,然后选择
      //第二个选项
    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'];
    }
    }


  2. 在坐着OnMouseUp

      //第三选项
    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)* ) - (x4-x3)*(y2-y1)))*(x2-x1));
thisY = Math.round(y1 +((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3))/(y4-y3)* ) - (x4-x3)*(y2-y1)))*(y2-y1));

//我必须为其他检查,否则角落(当两个条件为真时)无法处理
//所以我会一个接一个地处理
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)* ) - (x4-x3)*(y2-y1)))*(x2-x1));
thisY = Math.round(y1 +((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3))/(y4-y3)* ) - (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)* ) - (x4-x3)*(y2-y1)))*(x2-x1));
thisY = Math.round(y1 +((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3))/(y4-y3)* ) - (x4-x3)*(y2-y1)))*(y2-y1));
x2 = ThisX;
y2 = thisY;
}

if(y2> canvas.height - 1){//底边
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)* ) - (x4-x3)*(y2-y1)))*(x2-x1));
thisY = Math.round(y1 +((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3))/(y4-y3)* ) - (x4-x3)*(y2-y1)))*(y2-y1));
}

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

}



http://jsfiddle.net/WolfeSVK/s2tNr/


I am having issues implementing dragging functionality with HTML5 Canvas. I understand the lack of a scene graph etc., and have set up a way to identify drag a rectangle on mouse events.

However: the problem is losing mouse events when the mouse leaves the Canvas. If I drag outside of the canvas and release the mouse button, my code doesn't get a mouseup event to alter the dragging logic accordingly. The dragged object then remains stuck to my mouse until I start dragging again.

fabric.js doesn't have this problem, but I can't identify the relevant code in the library. How does it do this?

First use boolean variable isMouseDragged which is set true after mouseDown and false after mouseUp (or another event I'll explain later)

You can handle dragging several ways.

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

  1. On mouse up calculate intersection between point where you pressed and released button (imagine it as line) and edge of canvas beyond which is mouse pointer (imagine it as another line). Put mouseUp position as intersection of these two lines.

    // 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'];
        }
    }
    

  2. Hold your virtual mouse pointer (coordinates) inside a canvas.

    // 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'];
        }
    }
    

  3. Make coordinates onMouseUp = onMouseOut as you go out of canvas and set isMouseDragged false.

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

To calculate an intersect on edge of the canvas:

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

}

Look at the source code: http://jsfiddle.net/WolfeSVK/s2tNr/