Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get this HTML5 Canvas paint application to work for both touch and mouse events?

Here is the source code of what I'm trying to do:

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;
}

I tried adding event listeners for mouse down/up/move but those didn't seem to work.

Alternatively, if anyone has any suggestions for open source canvas painting apps that work on computer and tablet I'd rather just use that.

So far the only one that has stood out is https://github.com/PlayMyCode/SkyBrush but it unfortunately doesn't work on android tablets (at least the ones I've been able to try).

like image 922
Josh Avatar asked May 18 '13 21:05

Josh


People also ask

Is HTML5 Canvas still used?

The HTML5 canvas has the potential to become a staple of the web, enjoying ubiquitous browser and platform support in addition to widespread webpage support, as nearly 90% of websites have ported to HTML5.

What is the function of the new HTML5 Canvas element?

The CANVAS element allows you to add so much more interactivity to your web pages because now you can control the graphics, images, and text dynamically with a scripting language. The CANVAS element helps you turn images, photos, charts, and graphs into animated elements.

Does HTML5 Canvas work on mobile?

HTML5 Canvas is supported by all major browsers and can be accessed from desktops, tablets, and smartphones – once created a canvas application can run almost anywhere (unlike Flash and Silverlight). HTML5 Canvas offers great portability from desktops to mobile devices.

Is canvas new in HTML5?

Canvas is a new element in HTML5, which provides APIs that allow you to dynamically generate and render graphics, charts, images, and animation. The presence of the Canvas API for HTML5, strengthens the HTML5 platform by providing two-dimensional drawing capabilities.


1 Answers

Check the modified fiddle

I added a way to detect when running in a touch device and a switch to map the mouse events to touch events.

Also notice that when touchend occurred we need to use event.changedTouches to get the coors correctly.

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
like image 68
Gustavo Carvalho Avatar answered Sep 23 '22 17:09

Gustavo Carvalho