45

I am trying to capture touch coordinate on the touchend event but get undefined. The touchstart event works good, but same concept fails on touchend. I built this code with mousedown and mouseup and that works good.

What am I missing?

div.addEvent("touchstart", function (event) {
    event.preventDefault(); // to avoid scrolling
    span.innerHTML = event.page.x;
});
div.addEvent("touchend", function (event) {
    span.innerHTML = event.page.x;
});

FIDDLE

Rikard
  • 7,485
  • 11
  • 55
  • 92

6 Answers6

41

You need to store the values on touchmove and read it in touchend.

var lastMove = null;

// Save the touchstart to always have a position
div.addEvent('touchstart', function(event) {
  lastMove = event;
});

// Override with touchmove, which is triggered only on move
div.addEvent('touchmove', function(event) {
  lastMove = event;
});
adrenalin
  • 1,656
  • 1
  • 15
  • 25
  • Was it that easy? thanks! Why does it work without `mousemove` on `mouseup`? – Rikard Jul 30 '13 at 21:28
  • 1
    That I don't know. And I would have guessed that touchend event would have included the position where it ended, but maybe there are corner cases where it isn't possible to give, like when the touch exits the area (not possible to give explicit value of the **current** even if the previous was known). `mouseup` then again is *always* inside the area and `mouseout` is used when the area is exited. – adrenalin Jul 30 '13 at 21:32
  • 3
    The correct reason seems to be that touch events store the current touches and when touch ends, there are no current touches. – adrenalin Jul 30 '13 at 21:36
  • 14
    This came up as a solution to touchend from a Google search, but I always use event.changedTouches[0].pageX on touchend to get the coord, ala: http://jsfiddle.net/YrQjH/3/ – Darryl_Lehmann Jul 09 '14 at 13:50
  • 2
    I'm sorry but this answer is slightly incorrect because move is only triggered when the touch actually MOVES. A simple "click-like" touch will trigger touchstart, then touchend, and never touchmove. So yes you need to store the location in touchmove, but mostly also in touchstart in case there is no dragging. And in this case, the thing to store is the X,Y location, not the event. – FlorianB Sep 05 '16 at 19:23
39

I've been looking at the specification, the 4 touch events inherit from the touchEvent object, which has 3 list atributes containing information about all the touches (every finger on the screen) at the time of the event, each list saves touches based on this criteria:

changedTouches: Saves touches that have are out of the targeted element surface.

touches: Saves all current touches.

targetTouch: Saves all current touches that are within the surface of the target element.

The event touchend saves the position where the finger was lifted at changedTouches, and the nothing is saved in any of the other lists, therefore if you need to access this, you should use event.changedTouches[event.changedTouches.length-1], this returns a touch object with pageX and pageY atributes for coordinates.
The whole line would be:

span.innerHTML = event.changedTouches[event.changedTouches.length-1].pageX;


What I haven't been able to understand yet is if there's no coordinate atributes in the touchEvent object, why you get to use them at touchstart and touchmove events, and not with touchend. Maybe the implementation added this shortcut, or I missread.
David Villamizar
  • 802
  • 9
  • 16
14

You should use changedTouches instead touches in touchend

div.addEvent("touchstart", function (event) {
    event.preventDefault(); // to avoid scrolling
    span.innerHTML = event.pageX;
});
div.addEvent("touchend", function (event) {
    span.innerHTML = event.changedTouches[0].pageX;
});
idsbllp
  • 836
  • 9
  • 8
3

Though the question didn't ask for jQuery, try this code if you need a jQuery alternative. Works on all latest versions of jQuery.

$(document).on('touchstart', '.className', function (e) {
    console.log(e.originalEvent.touches[0].pageX);
});
$(document).on('touchend', '.className', function (e) {
    console.log(e.originalEvent.changedTouches[0].pageX);
});

You can optionally omit 'originalEvent', and use 'changedTouches' for JS only script and jQuery/browsers that doesn't support.

Ajay Singh
  • 692
  • 8
  • 19
1
touchStart(event) {
  this.startX = event.touches[0].pageX;
},
touchEnd(event) {
  this.endX = event.changedTouches[0].pageX;
},
邢博峰
  • 11
  • 1
  • 1
    Could you please expand on your answer by providing additional information? Just one or two sentences to explain your code will suffice. – Frits Apr 15 '17 at 08:18
0

I advise this works very well and can recover the same event attributes as a conventional computer ...

if(!('ontouchstart' in document.documentElement)){

Object.onmouseup = function(e){
      your code....
}

}else{

Object.ontouchend = function(e){
e = e.changedTouches[e.changedTouches.length-1];
      Your code....
}

}

very easy to manage.

*To manage your code use Google Chrome on a PC, in console mode it captures TOUCH events.

Cherif
  • 53
  • 2