29

I'm working on a html5 canvas game, but I don't know how to handle touch events. When a user touch the screen, and drag, then the browser will scroll the page. I would like to prevent it, and get the touch start, and touch end position. Is it possible?

Thanks in advance

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
Danny Fox
  • 38,659
  • 28
  • 68
  • 94

5 Answers5

48

You need to override the default touch behaviour to stop touchevents dragging the page. Clearly, you'll need to handle them again if your page becomes larger than the available area, but as you're making a game, going to assume you're doing 100%/100% layout.

function preventBehavior(e) {
    e.preventDefault(); 
};

document.addEventListener("touchmove", preventBehavior, {passive: false});

Edit: here's the W3C recommendation talking about touch events, which might be handy for you.

danp
  • 14,876
  • 6
  • 42
  • 48
  • 1
    This page does a great job explaining how touch events are handled: http://stackoverflow.com/questions/7056026/variation-of-e-touches-e-targettouches-and-e-changedtouches – David Apr 19 '13 at 12:14
  • 1
    In some cases you should also add `document.addEventListener("touchstart", preventBehavior, false);` to the code above to make it work. – optimizitor Mar 05 '17 at 12:52
  • 1
    recommend updating code example to pass { passive: false } as third argument as recommended by Jules below. This seems to be needed for this solution to work now. – Boog Aug 09 '18 at 19:15
24

Due to breaking changes made in recent versions of Chrome, the above answers are no longer correct. Attaching a touch event listener to the document or body elements will cause the event listener to be registered in "passive" mode, which causes calls to preventDefault to be ignored.

There are two solutions:

  • The preferred solution is to use the CSS style touch-action to specify that no scrolling should happen (e.g. with the value "none")

  • In cases where this is not appropriate (e.g. if the type of interaction should change dynamically in a way that cannot be determined before the gesture begins) then the event listener must be registered with the third parameter set to { passive: false } (you should perform browser detection to ensure that this style is supported first, though).

Jules
  • 14,841
  • 9
  • 83
  • 130
  • Thank you! touch-action: none solved my problem on the element that is being dragged. Very clean and short fix. – teamoo Oct 19 '22 at 12:43
10

If you don't want to use jQuery mobile or any other library then you can try this.

var startX, startY, endX, endY;
document.addEventListener("touchstart", function(e){
    startX = e.touches[0].pageX;
    startY = e.touches[0].pageY;

    e.preventDefault();//Stops the default behavior
}, false);

document.addEventListener("touchend", function(e){
    endX = e.touches[0].pageX;
    endY = e.touches[0].pageY;

    e.preventDefault();//Stops the default behavior
}, false);
ShankarSangoli
  • 69,612
  • 13
  • 93
  • 124
  • 1
    I didn't downvote but... You have some syntax errors and in your post you wrote "If you `don't` want to use jQuery mobile" then posted jQuery code. OP said he didn't want to use libraries. – Will Feb 12 '12 at 19:14
  • 1
    @WilliamVanRensselaer - Thanks for that I totally missed OP is not using jQuery either. I thought OP do not want jQuery mobile. But now modified my code to use plain JavaScript. – ShankarSangoli Feb 12 '12 at 19:21
  • @Danny - Try this, hope it will help you. – ShankarSangoli Feb 12 '12 at 19:21
  • That code will not work on iOS (don't know about Android) since, in "touchend", the touch event is removed from e.touches and put into e.changedTouches. See also http://stackoverflow.com/questions/7056026/variation-of-e-touches-e-targettouches-and-e-changedtouches – David Apr 19 '13 at 12:18
3
canvas.addEventListener('touchstart', function(e)
{
    alert(e.changedTouches[0].pageX + " " + e.changedTouches[0].pageY);
}
canvas.addEventListener('touchend', function(e)
{
    alert(e.changedTouches[0].pageX + " " + e.changedTouches[0].pageY);
}

Here's a good article about touching and gesturing on mobile phones:

http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/

papaiatis
  • 4,231
  • 4
  • 26
  • 38
1

Following solution preventing scroll when dragging AND at the same time usual scroll is working (when not dragging)

var scrollable = true;

var listener = function(e) {
    if (! scrollable) {
        e.preventDefault();
    }
}

document.addEventListener('touchmove', listener, { passive:false });


onDragstartHandler() {
  scrollable = false;
}

onDragendHandler(} {
  scrollable = true;
}

Don't forget to bind onDragstartHandler and onDragendHandler to related elements

Alex Golovin
  • 232
  • 3
  • 6