我在使用 HTML5 Canvas 实现拖动功能时遇到问题。我了解缺少场景图等,并设置了一种方法来识别鼠标事件上的拖动矩形。
然而:问题是当鼠标离开画布时丢失鼠标事件。如果我将鼠标拖动到画布之外并释放鼠标按钮,我的代码不会获得 mouseup 事件来相应地更改拖动逻辑。然后,拖动的对象将保持粘在我的鼠标上,直到我再次开始拖动。
Fabric.js没有这个问题,但我无法识别库中的相关代码。它是如何做到这一点的?
小智 5
首先使用布尔变量 isMouseDragged,它在 mouseDown 后设置为 true,在 mouseUp 后设置为 false(或我稍后将解释的另一个事件)
您可以通过多种方式处理拖动。
if (mouse['isMouseDragged']) {
mouse['xUp'] = e.clientX - canvas.getBoundingClientRect().left;
mouse['yUp'] = e.clientY - canvas.getBoundingClientRect().top;
...
Run Code Online (Sandbox Code Playgroud)
鼠标松开时,计算按下并释放按钮的点(将其想象为一条线)与鼠标指针超出的画布边缘(将其想象为另一条线)之间的交点。将 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'];
}
}
Run Code Online (Sandbox Code Playgroud)将虚拟鼠标指针(坐标)放在画布内。
// 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'];
}
}
Run Code Online (Sandbox Code Playgroud)当您离开画布时,将坐标设置为 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;
}
}
Run Code Online (Sandbox Code Playgroud)要计算画布边缘的相交:
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
};
Run Code Online (Sandbox Code Playgroud)
}
看源码: http: //jsfiddle.net/WolfeSVK/s2tNr/
| 归档时间: |
|
| 查看次数: |
2986 次 |
| 最近记录: |