touchイベント、tap、click、press、swipe
自動回転http://blog.mobiscroll.com/working-with-touch-events/
Working with touch イベント
Posted on アプリ16,2014 by Isti in R&D、 Tutoris
Last moth I was tensing the jQuery Europe conference in Vienna with the Mobiscroll team.The re was a session caled Getting touchywhich gave an insight into touch events and talked about why we need the m.The is a lot of ground that the presentation covers,so make sure to check out the sland.I would like to build to to to to to to to to excle and and and and and and and and and shence and and and and and and pance.
So why do we need touch events?
We don’t always need to use touch events.Turns out that mostly we can get away of using the reglar click becants because mobile browsers emulate the mouse the mousements.ramitware.mants.
The usual problems are:
Delayed event dispatch:mouse events are usualy fired with a delay,which makes the ap feel unreponsive.Mousemove doesn’t track,only a single emulated mousevent is fired.This makes impossible to make complex UI interfaces with gestures.The re are a ton of reources on the web targing these ises、so I’m not reinvent ting the where、I will just share my own personice on how I commbined and exted different solunt solunt solight.Moreediediediediediedble.
The click delay
As YOU probably know,there is a delay between the actual tap and the firing of the click event.I'm not going into details on why happens,you can read about it in the sledesmantioned before.
A common technique to prevent the delay is to bind the handler to both
However I find this problematic because:
Calling it on
Attach
When we started building the Listview,we imingied a widget with heavy gesture support.And this is where it shines.
We need support of follwing:
Use native vertical scrolling Handle left and right swipe gestures,disable page scroll during swipe gestures Handle tap Handle tap and hold Native scroll
If we want to keep using native touch scrolling,this involves that we cannot call
Horizontal swipe
ウェneed to listen to the
If the horizontal movement is more than 7 px,we consider it a swipe If the vertical movement is more than 10 px,we consider it a scroll Tap
We need to decide if the user is tapping on a list item or intens to swipe or scroll.If movement was less than 5 px iny direction tap is being hold.We also to to take care of the duplicate the ventine the the ventings,so
Tap&hold
On
Let’s take a look at our event handles.Also note that we atch the touch events and the
Android ICS
On Android ICS if no
Windows Phone
In WP 8 there isのway to prevent native scroll on the fly.To be able to listen to touch events,you need to set the following css property:
Firefox Mobile
In Firefox Mobile the native scroll can be killed only if preventDefault()is caled on the
sort will work with the aboove mentioned sort handle only(by calling)
What are your hacks and workounds for dealing with complex gestures?Let us know in the comment section below.
Tags: gestures Javascript、 listview touch events
Working with touch イベント
Posted on アプリ16,2014 by Isti in R&D、 Tutoris
Last moth I was tensing the jQuery Europe conference in Vienna with the Mobiscroll team.The re was a session caled Getting touchywhich gave an insight into touch events and talked about why we need the m.The is a lot of ground that the presentation covers,so make sure to check out the sland.I would like to build to to to to to to to to excle and and and and and and and and and shence and and and and and and pance.
So why do we need touch events?
We don’t always need to use touch events.Turns out that mostly we can get away of using the reglar click becants because mobile browsers emulate the mouse the mousements.ramitware.mants.
The usual problems are:
Delayed event dispatch:mouse events are usualy fired with a delay,which makes the ap feel unreponsive.Mousemove doesn’t track,only a single emulated mousevent is fired.This makes impossible to make complex UI interfaces with gestures.The re are a ton of reources on the web targing these ises、so I’m not reinvent ting the where、I will just share my own personice on how I commbined and exted different solunt solunt solight.Moreediediediediediedble.
The click delay
As YOU probably know,there is a delay between the actual tap and the firing of the click event.I'm not going into details on why happens,you can read about it in the sledesmantioned before.
A common technique to prevent the delay is to bind the handler to both
touchend
and click
events.The challenge here is to prevent the so caled「phantom click」、meaning that if your handled was caled on touch end、don’t execute it again when the click is emulated bythe brever.soure.soure.soure.sour provent e.preventDefault()
ether on touchstart
or touchend
which will prevent the firing of emulated mouse events.However I find this problematic because:
Calling it on
touchstart
will kill native page scroll Calling it on touchend
will kill momenum scroll on some devices It does not prevent at AL emulated events on Android 4.x stock browses The solution we are using in Mobiscroll does the follwing:Attach
touchstart
、 touchend
and click
events Remember start and end coordination Call the handler e.preventDefault()
オン touchend
,but only if movement was less then 20 px in any direct(so the user did not have the intent to scroll)Set a flagt to prevent executing the handler again in the emulated click event Start a timeout which will clear the flagh in case when the click event was not emulated Putting everrything together:var startX,
startY,
tap;
function getCoord(e, c) {
return /touch/.test(e.type) ? (e.originalEvent || e).changedTouches[0]['page' + c] : e['page' + c];
}
function setTap() {
tap = true;
setTimeout(function () {
tap = false;
}, 500);
}
element.on('touchstart', function (ev) {
startX = getCoord(ev, 'X');
startY = getCoord(ev, 'Y');
}).on('touchend', function (ev) {
// If movement is less than 20px, execute the handler
if (Math.abs(getCoord(ev, 'X') - startX) < 20 && Math.abs(getCoord(ev, 'Y') - startY) < 20) {
// Prevent emulated mouse events
ev.preventDefault();
handler.call(this, ev);
}
setTap();
}).on('click', function (ev) {
if (!tap) {
// If handler was not called on touchend, call it on click;
handler.call(this, ev);
}
ev.preventDefault();
});
Working with gesturesWhen we started building the Listview,we imingied a widget with heavy gesture support.And this is where it shines.
We need support of follwing:
Use native vertical scrolling Handle left and right swipe gestures,disable page scroll during swipe gestures Handle tap Handle tap and hold Native scroll
If we want to keep using native touch scrolling,this involves that we cannot call
e.preventDefault()
on any of the touch events unconditionaly.Horizontal swipe
ウェneed to listen to the
touchmove
event and decide on the fly whether it will be a vertical or horizontal swipe.If it’s horizontal swipe,kill the page scroll with call e.preventDefault()
.The following with ress holds ared:If the horizontal movement is more than 7 px,we consider it a swipe If the vertical movement is more than 10 px,we consider it a scroll Tap
We need to decide if the user is tapping on a list item or intens to swipe or scroll.If movement was less than 5 px iny direction tap is being hold.We also to to take care of the duplicate the ventine the the ventings,so
Tap&hold
On
touchstart
we will start a timer which activates the「sort/reorder」mode after a delay.This timer is being reet in case of a scroll,swipe,or touchend
.Let’s take a look at our event handles.Also note that we atch the touch events and the
mousedown
to the element itself,while the mousemove
and mouseup
events aratached to the document element dynamically and removed at the end.That is because the y behave differently:the touchmove
and touchend
will still be fired if the finger leaves the element,while the mousemove
and mouseend
event will not fire once the mouse pointer has left the element.var touch,
action,
diffX,
diffY,
endX,
endY,
scroll,
sort,
startX,
startY,
swipe,
function testTouch(e) {
if (e.type == 'touchstart') {
touch = true;
} else if (touch) {
touch = false;
return false;
}
return true;
}
function onStart(ev) {
if (testTouch(ev) && !action) {
action = true;
startX = getCoord(ev, 'X');
startY = getCoord(ev, 'Y');
diffX = 0;
diffY = 0;
sortTimer = setTimeout(function () {
sort = true;
}, 200);
if (ev.type == 'mousedown') {
$(document).on('mousemove', onMove).on('mouseup', onEnd);
}
}
}
function onMove(ev) {
if (action) {
endX = getCoord(ev, 'X');
endY = getCoord(ev, 'Y');
diffX = endX - startX;
diffY = endY - startY;
if (!sort && !swipe && !scroll) {
if (Math.abs(diffY) > 10) { // It's a scroll
scroll = true;
// Android 4.0 will not fire touchend event
$(this).trigger('touchend');
} else if (Math.abs(diffX) > 7) { // It's a swipe
swipe = true;
}
}
if (swipe) {
ev.preventDefault(); // Kill page scroll
// Handle swipe
// ...
}
if (sort) {
ev.preventDefault(); // Kill page scroll
// Handle sort
// ....
}
if (Math.abs(diffX) > 5 || Math.abs(diffY) > 5) {
clearTimeout(sortTimer);
}
}
}
function onEnd(ev) {
if (action) {
action = false;
if (swipe) {
// Handle swipe end
// ...
} else if (sort) {
// Handle sort end
// ...
} else if (!scroll && Math.abs(diffX) < 5 && Math.abs(diffY) < 5) { // Tap
if (ev.type === 'touchend') { // Prevent phantom clicks
ev.preventDefault();
}
// Handle tap
// ...
}
swipe = false;
sort = false;
scroll = false;
clearTimeout(sortTimer);
if (ev.type == 'mouseup') {
$(document).off('mousemove', onMove).off('mouseup', onEnd);
}
}
}
element
.on('touchstart mousedown', onStart)
.on('touchmove', onMove)
.on('touchend touchcancel', onEnd)
Problems that are still unsolivedAndroid ICS
On Android ICS if no
preventDefault
is caled on touchstart
or the first touchmove
、フテルーtouchmove
events and the touchend
will not be fired.As a workound we ned to decide in the first touchmove
if this is a scroll(so we don't call) preventDefault
)and then manaualy trigger touchend
– see the code above.Windows Phone
In WP 8 there isのway to prevent native scroll on the fly.To be able to listen to touch events,you need to set the following css property:
touch-action: none;
However this will kill default behavior、like native page scroll.Fortunately this can be fine tuned、so for the Listview we the follwing:touch-action: pan-y;
Which tells to broowser that vertical swipe will be handed by the browser、while our code will Tale care of the horizontal swipe.Ufortutututututututututuney sorting won't t be woking、becausitwill will not preveveveventatttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttch has the touch-action: none;
rule apple.So when the user“picks”up an item from the sort handle,we know he intens to reorder.Firefox Mobile
In Firefox Mobile the native scroll can be killed only if preventDefault()is caled on the
touchstart
event.Unfortunaryat touchstart
we don’t really know if we want scroll or not.This has two consequences:sort will work with the aboove mentioned sort handle only(by calling)
preventDefault()
on touchstart
if dragged by the handle)while swiping an item left or right vertical scroll will still work The ises can easure disappear in up comming browser udates or releass、until then we need to come up with worlounds.What are your hacks and workounds for dealing with complex gestures?Let us know in the comment section below.
Tags: gestures Javascript、 listview touch events