滚动时画布签名改变鼠标绘制位置

7

我正在尝试使用canvas,让人们可以用鼠标书写签名。一切正常,直到我拉伸或滚动屏幕,这时它就会在不同的位置画出线条,而不是在鼠标附近。

代码:

function onMouseUp(event) {
    'use strict';
    mousePressed = false;
}
function onMouseMove(event) {
    'use strict';
    if (mousePressed) {
        event.preventDefault();
        mouseX = event.clientX - can.offsetLeft - mleft;
        mouseY = event.clientY - can.offsetTop - mtop;
        ctx.lineTo(mouseX, mouseY);
        ctx.stroke();
    }
}
function onMouseDown(event) {
    'use strict';
    mousePressed = true;
    mouseX = event.clientX - can.offsetLeft - mleft;
    mouseY = event.clientY - can.offsetTop - mtop;
    ctx.beginPath();
    ctx.moveTo(mouseX, mouseY);
}
can.addEventListener('mousemove', onMouseMove, false);
can.addEventListener('mousedown', onMouseDown, false);
can.addEventListener('mouseup', onMouseUp, false);

HTML的代码如下: <canvas id="signature" width="567" height="150"></canvas>

该代码用于创建一个名为“signature”的画布,它的宽度为567像素,高度为150像素。

5个回答

2

看起来你只需要一种更可靠的方法,在页面重新排版时获取相对坐标。

@RyanArtecona 根据 这个有关鼠标相对于画布的坐标的问题 编写了以下函数:

function relMouseCoords(event){
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do{
        totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
        totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
    }
    while(currentElement = currentElement.offsetParent)

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    return {x:canvasX, y:canvasY}
}
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;

这很方便,因为它在HTMLCanvasElement函数的原型上添加了一个获取相对坐标的函数,这意味着您只需传递要使用的画布的引用,就可以获得相对于它的坐标。
使用此方法,您可以将mousedown函数重写为以下内容(您还需要对其他函数进行修改,但这仅作为示例):
function onMouseDown(event) {
    'use strict';
    mousePressed = true;
    // get a reference to the 'signature' canvas
    var canvas = document.getElementById('signature');
    // this returns an object with 'x' and 'y' properties
    var mouse = canvas.relMouseCoords(event)
    ctx.beginPath();
    // use the coordinates you got
    ctx.moveTo(mouse.x, mouse.y);
}

2

event.clientX/Y相对于视口的左上角而言,不考虑滚动。 event.pageX/Y相对于文档而言,因此它是包括滚动在内的事件发生时屏幕上的位置。您可以将所有关于clientX的引用更改为pageX,将所有关于clientY的引用更改为pageY,这样就应该可以正常工作。

解释每个屏幕/页面/客户端XY的区别。


1

更改这两行内容

mouseX = event.clientX - can.offsetLeft - mleft;
mouseY = event.clientY - can.offsetTop - mtop;

to

mouseX = event.offsetX || event.layerX;
mouseY = event.offsetY || event.layerY;

在您的两个处理程序中,浏览器可以为您处理相对坐标,而无需进行任何特殊的数学计算。 offsetX/Y 似乎是 Chrome/IE 特有的,而 layerX/Y 则可获得 Firefox 支持。
这里是一个 jsfiddle。我做了一些声明上的小改变,以使您的 use strict 起作用,因为我们好像缺少了一些代码。

0

将屏幕的滚动偏移添加到鼠标X和鼠标Y位置。使用jQuery,代码如下:

mouseX = event.clientX - can.offsetLeft - mleft + $(window).scrollLeft;
mouseY = event.clientY - can.offsetTop - mtop + $(window).scrollTop;

0
这不是一个简单的答案。找到最好的方法是从良好的基础开始,然后根据您的情况进行增量更改。我看过的关于这个主题的最好的文章来自Internet Explorer团队: 在所有浏览器中处理多点触控和鼠标输入 这篇文章将为您提供正确捕获鼠标输入的良好基础。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接