创建一个响应鼠标点击和触摸的 canvas

Create a canvas that responds to both mouseclick(s) and touch

我有一个 canvas 可以响应鼠标点击(或者在我更改代码之前一直响应),我正在尝试实现一部分脚本来响应触摸(ipad,智能手机、平板电脑等)。但是,我被困在两者之间;当我尝试一种方法时,它会破坏另一种方法,反之亦然。

想法?

<script type="text/javascript">
    var canvas, ctx, canvasX, canvasY, mouseIsDown = 0;

    function init() {
        canvas = document.getElementById("can");
        ctx = canvas.getContext("2d");

        canvas.addEventListener("mousedown", mouseDown, false);
        canvas.addEventListener("mousemove", mouseXY, false);
        canvas.addEventListener("touchstart", touchDown, false);
        canvas.addEventListener("touchmove", touchXY, true);
        canvas.addEventListener("touchend", touchUp, false);

        document.body.addEventListener("mouseup", mouseUp, false);
        document.body.addEventListener("touchcancel", touchUp, false);
    }

    function mouseUp() {
        mouseIsDown = 0;
        mouseXY();
    }

    function touchUp() {
        mouseIsDown = 0;
        // no touch to track, so just show state
        showPos();
    }

    function mouseDown() {
        mouseIsDown = 1;
        mouseXY();
    }

    function touchDown() {
        mouseIsDown = 1;
        touchXY();
    }

    function mouseXY(e) {
        if (!e)
            var e = event;
        canvasX = e.pageX - canvas.offsetLeft;
        canvasY = e.pageY - canvas.offsetTop;
        showPos();
    }

    function touchXY(e) {
        if (!e)
            var e = event;
        e.preventDefault();
        canvasX = e.targetTouches[0].pageX - canvas.offsetLeft;
        canvasY = e.targetTouches[0].pageY - canvas.offsetTop;
        showPos();
    }

function color(obj) {
    switch (obj.id) {
        case "green":
            x = "green";
            break;
        case "blue":
            x = "blue";
            break;
        case "red":
            x = "red";
            break;
        case "yellow":
            x = "yellow";
            break;
        case "orange":
            x = "orange";
            break;
        case "black":
            x = "black";
            break;
        case "white":
            x = "white";
            break;
    }
    if (x == "white") y = 14;
    else y = 2;

}

function draw() {
    ctx.beginPath();
    ctx.moveTo(prevX, prevY);
    ctx.lineTo(currX, currY);
    ctx.strokeStyle = x;
    ctx.lineWidth = y;
    ctx.stroke();
    ctx.closePath();
}

function erase() {
    var m = confirm("Want to clear");
    if (m) {
        ctx.clearRect(0, 0, w, h);
        document.getElementById("canvasimg").style.display = "none";
    }
}

function save() {
    document.getElementById("canvasimg").style.border = "2px solid";
    var dataURL = canvas.toDataURL();
    document.getElementById("canvasimg").src = dataURL;
    document.getElementById("canvasimg").style.display = "inline";
}

function findxy(res, e) {
    if (res == 'down') {
        prevX = currX;
        prevY = currY;
        currX = e.clientX - canvas.offsetLeft;
        currY = e.clientY - canvas.offsetTop;

        flag = true;
        dot_flag = true;
        if (dot_flag) {
            ctx.beginPath();
            ctx.fillStyle = x;
            ctx.fillRect(currX, currY, 2, 2);
            ctx.closePath();
            dot_flag = false;
        }
    }
    if (res == 'up' || res == "out") {
        flag = false;
    }
    if (res == 'move') {
        if (flag) {
            prevX = currX;
            prevY = currY;
            currX = e.clientX - canvas.offsetLeft;
            currY = e.clientY - canvas.offsetTop;
            draw();
        }
    }
}
</script>

您没有将事件对象传递给任何处理程序:

这个:

function mouseUp() {
    mouseIsDown = 0;
    mouseXY();
}

应该是:

function mouseUp(e) {  // <- e
    mouseIsDown = 0;
    mouseXY(e);        // e ->
}

(其他类似)

使用 pageX/Y 也要小心,因为它们是 not part of any standard:

This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

最好结合使用 getBoundingClientRect()clientX/Y:

function mouseXY(e) {
    var rect = canvas.getBoundingClientRect();
    canvasX = e.clientX - rect.left;
    canvasY = e.clientY - rect.top;
    showPos();
}

您还可以通过从触摸处理程序传入触摸对象来合并 mouseXY()/touchXY()

function touchDown(e) {
    mouseIsDown = 1;
    mouseXY(e.targetTouches[0]);
}