我如何让这个HTML5 Canvas绘画应用程序同时适用于触摸和鼠标事件?



下面是我要做的事情的源代码:

http://jsfiddle.net/3nGtM/

Javascript:

    window.addEventListener('load', function () {
    // get the canvas element and its context
    var canvas = document.getElementById('sketchpad');
    var context = canvas.getContext('2d');
    // create a drawer which tracks touch movements
    var drawer = {
        isDrawing: false,
        touchstart: function (coors) {
            context.beginPath();
            context.moveTo(coors.x, coors.y);
            this.isDrawing = true;
        },
        touchmove: function (coors) {
            if (this.isDrawing) {
                context.lineTo(coors.x, coors.y);
                context.stroke();
            }
        },
        touchend: function (coors) {
            if (this.isDrawing) {
                this.touchmove(coors);
                this.isDrawing = false;
            }
        }
    };
    // create a function to pass touch events and coordinates to drawer
    function draw(event) {
        // get the touch coordinates
        var coors = {
            x: event.targetTouches[0].pageX,
            y: event.targetTouches[0].pageY
        };
        // pass the coordinates to the appropriate handler
        drawer[event.type](coors);
    }
    // attach the touchstart, touchmove, touchend event listeners.
    canvas.addEventListener('touchstart', draw, false);
    canvas.addEventListener('touchmove', draw, false);
    canvas.addEventListener('touchend', draw, false);
    // prevent elastic scrolling
    document.body.addEventListener('touchmove', function (event) {
        event.preventDefault();
    }, false); // end body.onTouchMove
}, false); // end window.onLoad
HTML:

<body>
    <div id="container">
        <canvas id="sketchpad" width="400" height="400">Sorry, your browser is not supported.</canvas>
    </div>
</body>
CSS:

body {
    margin:0;
    padding:0;
    font-family:Arial;
}
#container {
    position:relative;
}
#sketchpad {
    border: 1px solid #000;
}

我试着为鼠标上下移动添加事件监听器,但这些似乎不起作用。

或者,如果有人有任何建议的开源画布绘画应用程序,在电脑和平板电脑上工作,我宁愿使用它。

到目前为止,唯一一个脱颖而出的是https://github.com/PlayMyCode/SkyBrush,但不幸的是,它不能在android平板电脑上工作(至少我已经尝试过的那些)。

检查修改后的小提琴

我添加了一种方法来检测何时在触摸设备中运行,以及将鼠标事件映射到触摸事件的开关。

还请注意,当触摸端发生时,我们需要使用event.changedTouches来正确获取coors

window.addEventListener('load', function () {
// get the canvas element and its context
var canvas = document.getElementById('sketchpad');
var context = canvas.getContext('2d');
// create a drawer which tracks touch movements
var drawer = {
    isDrawing: false,
    touchstart: function (coors) {
        context.beginPath();
        context.moveTo(coors.x, coors.y);
        this.isDrawing = true;
    },
    touchmove: function (coors) {
        if (this.isDrawing) {
            context.lineTo(coors.x, coors.y);
            context.stroke();
        }
    },
    touchend: function (coors) {
        if (this.isDrawing) {
            this.touchmove(coors);
            this.isDrawing = false;
        }
    }
};
// create a function to pass touch events and coordinates to drawer
function draw(event) { 
    var type = null;
    // map mouse events to touch events
    switch(event.type){
        case "mousedown":
                event.touches = [];
                event.touches[0] = { 
                    pageX: event.pageX,
                    pageY: event.pageY
                };
                type = "touchstart";                  
        break;
        case "mousemove":                
                event.touches = [];
                event.touches[0] = { 
                    pageX: event.pageX,
                    pageY: event.pageY
                };
                type = "touchmove";                
        break;
        case "mouseup":                
                event.touches = [];
                event.touches[0] = { 
                    pageX: event.pageX,
                    pageY: event.pageY
                };
                type = "touchend";
        break;
    }        
    // touchend clear the touches[0], so we need to use changedTouches[0]
    var coors;
    if(event.type === "touchend") {
        coors = {
            x: event.changedTouches[0].pageX,
            y: event.changedTouches[0].pageY
        };
    }
    else {
        // get the touch coordinates
        coors = {
            x: event.touches[0].pageX,
            y: event.touches[0].pageY
        };
    }
    type = type || event.type
    // pass the coordinates to the appropriate handler
    drawer[type](coors);
}
// detect touch capabilities
var touchAvailable = ('createTouch' in document) || ('ontouchstart' in window);
// attach the touchstart, touchmove, touchend event listeners.
if(touchAvailable){
    canvas.addEventListener('touchstart', draw, false);
    canvas.addEventListener('touchmove', draw, false);
    canvas.addEventListener('touchend', draw, false);        
}    
// attach the mousedown, mousemove, mouseup event listeners.
else {
    canvas.addEventListener('mousedown', draw, false);
    canvas.addEventListener('mousemove', draw, false);
    canvas.addEventListener('mouseup', draw, false);
}
// prevent elastic scrolling
document.body.addEventListener('touchmove', function (event) {
    event.preventDefault();
}, false); // end body.onTouchMove
}, false); // end window.onLoad