javascript + html5 canvas: drawing instead of dragging/scrolling on mobile devices?

iPad / iPhone doesn't have mouse* events. You need to use touchstart, touchmove and touchend. This events can have multiple touches so you need to get first one like this:

canvas.ontouchstart = function(e) {
  if (e.touches) e = e.touches[0];
  return false;
}

It's important to return false in touch start method because otherwise page scroll is triggered.


I'm going to add to Grassator's answer by adding a link to this answer that goes more in-depth with the code required to make this solution work: https://stackoverflow.com/a/16630678/5843693.

Before I continue, please note that Apple has changed the way iOS handles scrolling on more recent devices. To handle this change, it is necessary to add a few extra functions; thanks to Christopher Vickers for sharing this:

function preventDefault(e) {
    e.preventDefault();
}
function disableScroll() {
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll() {
    document.body.removeEventListener('touchmove', preventDefault);
}

The methods for canvas are all called upon in a drawer fashion like so:

var drawer = {
   isDrawing: false,
   touchstart: function (coors) {
      ctx.beginPath();
      ctx.moveTo(coors.x, coors.y);
      this.isDrawing = true;
      disableScroll(); // add for new iOS support
   },
   touchmove: function (coors) {
      if (this.isDrawing) {
         ctx.lineTo(coors.x, coors.y);
         ctx.stroke();
      }
   },
   touchend: function (coors) {
      if (this.isDrawing) {
         this.touchmove(coors);
         this.isDrawing = false;
      }
      enableScroll(); // add for new iOS support
   }
};

In addition, EventListeners are specifically ordered so that touch inputs are taken first:

var touchAvailable = ('createTouch' in document) || ('onstarttouch' in window);

if (touchAvailable) {
   canvas.addEventListener('touchstart', draw, false);
   canvas.addEventListener('touchmove', draw, false);
   canvas.addEventListener('touchend', draw, false);
} else {
   canvas.addEventListener('mousedown', draw, false);
   canvas.addEventListener('mousemove', draw, false);
   canvas.addEventListener('mouseup', draw, false);
}

Finally, the "elastic" scrolling is prevented by adding one more EventListener near the end of the code.

document.body.addEventListener('touchmove', function (event) {
   event.preventDefault();
}, false);

All of this is placed inside window.addEventListener('load', function () {}).