When a touchend event occurs, is it possible to know where the touch began (touchstart co-ordinates)? On first glance, this looks as easy as saving the coordinates during touchstart, but suppose the event is attached to all DOM elements with a particular class (ie. .special
). Now consider that I touch two objects with the .special
class then lift my finger off one. I can't just look at the last saved value, because it could be the first finger that I lifted up.
How can I retrieve the touchstart coordinates in these circumstances?
On touchstart
you can store all the values you may need (like x, y, target, an so on). On touchend
you may retrieve all the stored values thanks to the Touch.identifier
value which should be unique for each touch.
I have created a proof of concept here: http://jsbin.com/adifit/3/
The code below keeps track of x
and y
position only, but you can track any of the properties if you need.
The idea behind the code is:
touchstart
create an object and store all the data inside (including the touch ID)touchend
check the id of the touch and try to find corresponding object in the arrayAnd the code:
var touches = [];
var cons;
$(init);
function init()
{
cons = $("#console");
document.getElementById("area").addEventListener("touchstart", onTouchStart);
document.addEventListener("touchend", onTouchEnd);
document.addEventListener("touchcancel", onTouchEnd);
}
function onTouchStart(e)
{
e.preventDefault();
var touchList = e.changedTouches;
var touch;
for(var i = 0; i < touchList.length; i++)
{
cons.html(cons.html() + "startX: " + touchList[i].screenX + ", id: " + touchList[i].identifier + "<br/>");
touch = {x: touchList[i].screenX, y: touchList[i].screenY, id: touchList[i].identifier};
touches.push(touch);
}
}
function onTouchEnd(e)
{
cons.html(cons.html() + "<strong>TouchEnd:</strong><br/>");
var touchList = e.changedTouches;
var touch;
for(var i = 0; i < touchList.length; i++)
{
touch = {x: touchList[i].screenX, y: touchList[i].screenY, id: touchList[i].identifier};
for (var j = touches.length - 1; j >= 0 ; j--)
{
if (touches[j].id == touch.id)
{
cons.html(cons.html() + "<strong>startX: "+ touches[j].x+ ", id: " + touchList[i].identifier + "</strong><br/>");
touches.splice(j, 1);
}
}
}
}
The code above uses jQuery, but it is used only for convenience of displaying the results on screen, jQuery is not used for anything else.
Different touch
events can be connected trough the event.target
.
W3C specs on touchmove
event:
The target of this event must be the same Element that received the touchstart event when this touch point was placed on the surface, even if the touch point has since moved outside the interactive area of the target element.
So you keep track of the event.target
:
document.addEventListener("touchstart", onTouchStart);
document.addEventListener("touchend", onTouchEnd);
document.addEventListener("touchcancel", onTouchCancel);
var targets = []; // create array with all touch targets
// still needs some sort of garbage collection though
function onTouchStart(event){
targets.push(event.target); // add target to array
}
function onTouchEnd(event){
// loop through array to find your target
for (var i = 0; i < targets.length; i++) {
if (targets[i] == event.target) { //test target
// this is your match! Do something with this element
targets[i].splice(i,1); // remove entry after event ends;
}
}
}
function onTouchCancel(event){
// loop through array to find your target
for (var i = 0; i < targets.length; i++) {
if (targets[i] == event.target) { //test target
// Just delete this event
targets[i].splice(i,1); // remove entry after event ends;
}
}
}
NOTE: not tested. I see that @Strah has a good solution, mine is a bit simplified and only checks the event.target, not the touch-id. But it demonstrates a similar concept.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With