mousemove事件是否根据鼠标方向而有不同的行为?

huangapple go评论91阅读模式
英文:

Does mousemove event act differently according to mouse direction?

问题

I have the following piece of code

canvas1.addEventListener('mousedown', function(e) {
    var x = e.clientX - canvas1.getBoundingClientRect().left;
    var y = e.clientY - canvas1.getBoundingClientRect().top;

    if (rect.currentActiveBox == currentActiveBox) {
        // In case we try to draw another box first, clear out the previous box.
        console.log('clearing ', rect);
        ctx.clearRect(rect.startX - 6, rect.startY - 6, rect.w + 8, rect.h + 8);
    }

    rect.startX = x;
    rect.startY = y;

    isDrawing = true;
    rect.currentActiveBox = currentActiveBox;
    rects[currentActiveBox] = JSON.parse(JSON.stringify(rect));
});

canvas1.addEventListener('mousemove', function(e) {
    if (isDrawing === true) {
        // rect.w = (e.pageX - this.offsetLeft) - rect.startX;
        // rect.h = (e.pageY - this.offsetTop) - rect.startY ;
        rect.w = e.pageX - rect.startX;
        rect.h = e.pageY - rect.startY;
        ctx.clearRect(rect.startX, rect.startY, rect.w, rect.h);
        ctx.beginPath();
        ctx.strokeStyle = "red";
        ctx.lineWidth = 3;
        ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
        rects[currentActiveBox] = JSON.parse(JSON.stringify(rect));
    }
});

which just draws a box as shown below
mousemove事件是否根据鼠标方向而有不同的行为?

However this only works if I drag the mouse from top to bottom manner. If I try dragging the mouse from bottom up, I get ghost boxes as shown below.

mousemove事件是否根据鼠标方向而有不同的行为?

I would expect the mousemove direction shouldn't change how the drawing happens. Is there something obvious that I might be missing?

英文:

I have the following piece of code

canvas1.addEventListener('mousedown', function(e) {
    var x = e.clientX - canvas1.getBoundingClientRect().left;
    var y = e.clientY - canvas1.getBoundingClientRect().top;

    if (rect.currentActiveBox == currentActiveBox) {
        // Incase we try to draw another box first clear out the previous box.
        console.log('clearing ', rect);
        ctx.clearRect(rect.startX - 6 , rect.startY - 6, rect.w + 8, rect.h + 8); 
    }

    rect.startX = x;
    rect.startY = y;

    isDrawing = true;
    rect.currentActiveBox = currentActiveBox;
    rects[currentActiveBox] = JSON.parse(JSON.stringify(rect));
});

canvas1.addEventListener('mousemove', function(e) {
    if(isDrawing === true) {
        // rect.w = (e.pageX - this.offsetLeft) - rect.startX;
        // rect.h = (e.pageY - this.offsetTop) - rect.startY ;
        rect.w = e.pageX - rect.startX;
        rect.h = e.pageY - rect.startY;
        ctx.clearRect(rect.startX, rect.startY, rect.w, rect.h);
        ctx.beginPath();
        ctx.strokeStyle = "red";
        ctx.lineWidth = 3;
        ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
        rects[currentActiveBox] = JSON.parse(JSON.stringify(rect));
    }
});

which just draws a box as shown below
mousemove事件是否根据鼠标方向而有不同的行为?

However this only works if I drag the mouse from top to bottom manner. If I try dragging the mouse from bottom up, I get ghost boxes as shown bellow.

mousemove事件是否根据鼠标方向而有不同的行为?

I would expect the mousemove direction shouldn't change how the drawing happens. Is there something obvious that I might be missing?

答案1

得分: 1

注意笔画的位置!

从技术上讲,它在您在坐标中指定的矩形的外部

因此,在您的 mousemove 函数中,当您执行 clearRect 时,您正在清除红线内部的区域,而不是红线本身。

在您的 mousedown 函数中,您会对左上角进行一些微调,然后继续更宽/更深,而不是标称的宽度/高度。

也许尝试一下在 mousemove 中进行微调?

例如,您可以尝试这样做:

        ...
        rect.h = e.pageY - rect.startY;
        ctx.clearRect(rect.startX-3, rect.startY-3, rect.w+6, rect.h+6);
        ctx.beginPath();
        ... 

如果这不起作用,尝试将 clearRect 替换为绘制不同颜色的矩形。这样,您可以检查它试图删除的位置,并确保它在您预期的位置。

英文:

Watch out for the position of the stroke!

It is technically outside the rectangle that you specify in the coordinates.

Therefore, in your mousemove function, when you clearRect, you are clearing the area inside the red lines, and not the red lines themselves.

Further up, in your mousedown function, you do some good fudging to start to the left/top, and proceed wider/deeper than the nominal width/height.

Perhaps try fudging your mousemove?

For example, you could try this:

        ...
        rect.h = e.pageY - rect.startY;
        ctx.clearRect(rect.startX-3, rect.startY-3, rect.w+6, rect.h+6);
        ctx.beginPath();
        ... 

If that doesn't work, try replacing the clearRect with a rect that draws a different colour. That way, you can check where it is trying to delete, and make sure that it is where you expect.

答案2

得分: 1

以下是翻译好的内容:

有几点需要注意:

  • 正如ProfDFrancis所指出的,您的描边实际上超出了边界框矩形,因此您需要扩展清除区域。
  • 您清除的是新矩形,而不是先前的矩形,因此如果指针移动超过1像素,将留下残留。
  • 您在指针偏移方面不一致 - pageXclientX不能互换使用,因此对于rect.wrect.h(似乎考虑了元素偏移,如mousedown处理程序中的情况)的注释计算是正确的。

您可以像这样做:

if(isDrawing === true) {
    const strokeSize = 3;
    
    // 计算描边触及的所有像素的边界框 - 请确保获得慷慨的边界以处理抗锯齿
    const clearLeft   = Math.min(rect.startX, rect.startX + rect.w) - strokeSize;
    const clearTop    = Math.min(rect.startY, rect.startY + rect.h) - strokeSize;
    const clearRight  = Math.max(rect.startX, rect.startX + rect.w) + strokeSize;
    const clearBottom = Math.max(rect.startY, rect.startY + rect.h) + strokeSize;
    ctx.clearRect(clearLeft, clearTop, clearRight - clearLeft, clearBottom - clearTop);
    
    rect.w = e.pageX - this.offsetLeft - rect.startX;
    rect.h = e.pageY - this.offsetTop - rect.startY;

    ctx.beginPath();
    // 等等
}

fiddle

英文:

There's a few things:

  • As ProfDFrancis has pointed out, your stroke actually extends outside the bounding box rectangle, so you need to expand your cleared area
  • You're clearing the new rectangle rather than the previous rectangle, so if the pointer movements are more than 1px at a time you will leave artifacts
  • You're being inconsistent with your pointer offsets – pageX and clientX are not interchangeable, so your commented-out calculation for rect.w and rect.h (which appears to take the element offset into consideration, as in the mousedown handler) is correct.

You could do something like:

    if(isDrawing === true) {
        const strokeSize = 3;
        
        // Compute bounding box for all pixels touched by the stroke –
        // be sure to get a generous border to cope with antialiasing
        const clearLeft   = Math.min(rect.startX, rect.startX + rect.w) - strokeSize;
		const clearTop    = Math.min(rect.startY, rect.startY + rect.h) - strokeSize;
        const clearRight  = Math.max(rect.startX, rect.startX + rect.w) + strokeSize;
        const clearBottom = Math.max(rect.startY, rect.startY + rect.h) + strokeSize;
        ctx.clearRect(clearLeft, clearTop, clearRight - clearLeft, clearBottom - clearTop);
        
        rect.w = e.pageX - this.offsetLeft - rect.startX;
        rect.h = e.pageY - this.offsetTop - rect.startY;

        ctx.beginPath();
        // etc
    }

fiddle

huangapple
  • 本文由 发表于 2023年4月7日 00:48:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75951911.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定