Download - Getting touchy - an introduction to touch and pointer events / Frontend NE / 2 March 2017
getting touchyAN INTRODUCTION TO TOUCH AND POINTER EVENTS
Patrick H. Lauke / Frontend NE / 2 March 2017
about me...• senior accessibility consultant at The Paciello Group
• previously developer relations at Opera
• co-editor Touch Events Level 2
• WG chair and co-editor Pointer Events Level 2
github.com/patrickhlauke/getting-touchy-presentation"evergreen" expanded version of this presentation
(and branches for specific conferences)
patrickhlauke.github.io/touch
Touch/pointer events test results
my JavaScript sucks... (but will hopefully convey the right concepts)
how can I make my website work on touch devices?
you don't need touch events browsers emulate regular
mouse events
patrickhlauke.github.io/touch/tests/event-listener_mouse-only.html
patrickhlauke.github.io/touch/tests/event-listener_mouse-only.html
compatibility mouse events(mouseenter) > mouseover > mousemove* > mousedown >
(focus) > mouseup > click* only a single sacrificial mousemove event fired
on first tap(mouseenter) > mouseover > mousemove >
mousedown > (focus) > mouseup > click
subsequent tapsmousemove > mousedown > mouseup > click
tapping away(mouseout) > (blur)
focus / blur only on focusable elements; subtle differences between browsers Mobile/tablet touchscreen activation/tap event order
emulation works, but is limiting/problematic
1. delayed event dispatch2. mousemove doesn't track
1. delayed event dispatch2. mousemove doesn't track
patrickhlauke.github.io/touch/tests/event-listener_show-delay.htmlless of a problem in modern browsers, but for iOS < 9.3 or older Androids still relevant
patrickhlauke.github.io/touch/tests/event-listener_show-delay.html
1. delayed event dispatch2. mousemove doesn't track
patrickhlauke.github.io/touch/particle/2
patrickhlauke.github.io/touch/particle/2
we need to go deeper...
touch events
introduced by Apple, adoptedin Chrome/Firefox/Opera
(and belatedly IE/Edge – more on that later)
www.w3.org/TR/touch-events
caniuse.com: Can I use touch events?
touchstart touchmove touchend
touchcancel
patrickhlauke.github.io/touch/tests/event-listener_all-no-timings.htmlBug 128534 - 'mouseenter' mouse compat event not fired...
events fired on taptouchstart > [touchmove]+ > touchend >
(mouseenter) > mouseover > mousemove > mousedown > (focus) > mouseup > click
(mouse events only fired for single-finger tap)
on first taptouchstart > [touchmove]+ > touchend >
(mouseenter) > mouseover > mousemove > mousedown > (focus) > mouseup > click
subsequent tapstouchstart > [touchmove]+ > touchend > mousemove > mousedown > mouseup > click
tapping awaymouseout > (mouseleave) > (blur)
• too many touchmove events prevent mouse compatibility events
after touchend (not considered a "clean" tap)
• too many touchmove events on activatable elements can lead to
touchcancel (in old Chrome/Browser versions)
• not all browsers consistently send touchmove• differences in focus / blur and some mouse compatibility events
(e.g. mouseenter / mouseleave )
• some events may only fire when tapping away to another focusable
element (e.g. blur )
some browsers outright weird...
Browser/Android 4.3mouseover > mousemove > touchstart > touchend >
mousedown > mouseup > click
Browser/Blackberry PlayBook 2.0touchstart > mouseover > mousemove > mousedown >
touchend > mouseup > click
UC Browser 10.8/Android 6mouseover > mousemove > touchstart > (touchmove)+ > touchend >
mousedown > focus > mouseup > click
Touch/pointer events test results
shouldn't affect your code,unless you're expecting a very
specific sequence...
<interlude >simple feature detection for
touch events
/� feature detection for touch events */ if ( 'ontouchstart' in window ) { /* some clever stuff here */ } /* older browsers have flaky support so more hacky tests needed...use Modernizr.touch or similar */
patrickhlauke.github.io/touch/tests/touch-feature-detect.html
/* conditional "touch OR mouse/keyboard" event binding */ if ('ontouchstart' in window) { // set up event listeners for touch ... } else { // set up event listeners for mouse/keyboard ... }
don't make it touch-exclusive
hybrid devices touch + mouse + keyboard
@patrick_h_lauke showing a naive "touch or mouse" issue on Flickr (which has since been fixed)
Bug 888304 - touch-events on Firefox-desktop should be disabled until we can support themproperly
Issue 392584: TouchEvent API should be enabled consistently
Chrome now returns window.TouchEvent on non-touch devicespatrickhlauke.github.io/touch/tests/touch-feature-detect.html
even on "mobile" we can havemultiple inputs...
Android + mouse – like touch (mouse emulating touch)touchstart > touchend > mouseover > mousemove > mousedown >
(focus) > mouseup > click
Blackberry PlayBook 2.0 + mouse – like desktopmouseover > mousedown > (mousemove)+ > mouseup > click
Blackberry Leap (BBOS 10.1) + mouse – like desktopmouseover > mousedown > (mousemove)+ > mouseup > click
Windows 10 Mobile/Microsoft Edge + mouse – like desktopmouse events (+ pointer events) + click
Windows 10 Mobile/Microsoft Edge + keyboard – like desktopfocus > click
Android + keyboard – like desktopfocus > click
iOS keyboard only works insame situations as on-screen
keyboard (e.g. text inputs, URL entry)
VoiceOver enables full keyboard access on iOS
iOS + keyboard – similar to touchfocus � touchstart > touchend > (mouseenter) > mouseover >
mousemove > mousedown > blur > mouseup > click
further scenarios?• desktop with external touchscreen
• touchscreen laptop with non-touch second screen
• touchscreen laptop with trackpad/mouse
• ...and other permutations?
no way to detect these cases...
Modernizr.touch detects touch events not touch devices
Stu Cox: “ou can't detect a touchscreen
hacks.mozilla.org - Detecting touch [...]
/* feature detection for touch events */ if ('ontouchstart' in window) { /* browser supports touch events but user is not necessarily using touch (exclusively) */ /* it could be a mobile, tablet, desktop, fridge ... */ }
touch or mouse or keyboard
touch and mouse and keyboard
what about CSS4 Media Queries?
W3C Media Queries Level 4 (Editor's Draft)
/* MQ4 Interaction Media Features*/ pointer: none | coarse | fine hover: none | hover any-pointer: none | coarse | fine any-hover: none | hover
hover: on-demand / any-hover: on-demand removed in recent drafts
dev.opera - Interaction Media Features and their potential (for incorrect assumptions)
patrickhlauke.github.io/touch/pointer-hover-any-pointer-any-hoverprimary input is unchanged (and Chrome/Android required a full restart)
/* Naive uses of Interaction Media Features */ @media (pointer: fine) { /* primary input has fine pointer precision... so make all buttons/controls small? */ } @media (hover: hover) { /* primary input has hover...so we can rely on it? */ } /* pointer and hover only check "primary" input, but what if there's a secondary input that lacks capabilities? */
/* Better uses of Interaction Media Features */ @media (any-pointer: coarse) { /* at least one input has coarse pointer precision... provide larger buttons/controls for touch */ } /* test for *any* "least capable" inputs (primary or not) */
Limitation: [mediaqueries-4] any-hover can't be used to detect mixed hover and non-hover
capable pointers. Also, pointer / hover / any-pointer / any-hover don't cover non-pointerinputs (e.g. keyboards) – always assume non-hover-capable inputs
@media (any-hover: none) {/* at least one input lacks hover capability...
don't rely on it or avoid altogether */}
detect which input the users isusing right now...
GitHub: ten1seven / what-input
Demo: What Input?
if in doubt, offer a way to switch interfaces... or just always use a touch-optimised interface
<� interlude >
touch events vs
limitations/problems
1. delayed event dispatch2. mousemove doesn't track
1. delayed event dispatch2. mousemove doesn't track
patrickhlauke.github.io/touch/tests/event-listener_show-delay.htmlless of a problem in modern browsers, but for iOS < 9.3 or older Androids still relevant
why the delay? double-tap to zoom
(mostly anyway)
when does the delay happen?
patrickhlauke.github.io/touch/tests/event-listener.html
touch / mouse events delaytouchstart > [touchmove]+ > touchend >
[300ms delay] (mouseenter) > mouseover > mousemove > mousedown >
(focus) > mouseup > click
how can we make it feelresponsive like a native app?
react to events fired before the300ms delay...
touchstart for animmediate control (e.g. fire/jump button on a game)
touchend for a control thatfires after finger lifted
(but this can result in events firing after zoom/scroll)
don't make it touch-exclusive
/* DON'T DO THIS: conditional "touch OR mouse/keyboard" event binding */ if ('ontouchstart' in window) { // set up event listeners for touch foo.addEventListener('touchend', ...); ... } else { // set up event listeners for mouse/keyboard foo.addEventListener('click', ...); ... }
patrickhlauke.github.io/touch/tests/event-listener_naive-touch-or-mouse.html
/* DO THIS: doubled-up "touch AND mouse/keyboard" event binding */ // set up event listeners for touch foo.addEventListener('touchend', ...); // set up event listeners for mouse/keyboard foo.addEventListener('click', ...); /* but this would fire our function twice for touch? */
patrickhlauke.github.io/touch/tests/event-listener_naive-event-doubling.html
/* DO THIS: doubled-up "touch AND mouse/keyboard" event binding */ // set up event listeners for touch foo.addEventListener('touchend', function(e) { // prevent compatibility mouse events and click e.preventDefault(); ... }); // set up event listeners for mouse/keyboard foo.addEventListener('click', ...);
patrickhlauke.github.io/touch/tests/event-listener_naive-event-doubling-fixed.html
preventDefault() kills scrolling, pinch/zoom, etc
apply preventDefault()carefully
(just on buttons/links, not entire page)
github.com/ftlabs/fastclick
patrickhlauke.github.io/touch/fastclick“ouTube: iOS/Safari 300ms click delay: vanilla Bootstrap and using fastclick.js
patrickhlauke.github.io/touch/fastclick/fastclick.html“ouTube: iOS/Safari 300ms click delay: vanilla Bootstrap and using fastclick.js
browsers working to removedouble-tap to zoom delay
non-scalable/zoomableviewport and
"double-tap to zoom"
<meta name="viewport" content="user-scalable=no">patrickhlauke.github.io/touch/tests/event-listener_user-scalable-no.html
Changeset 191072 - Web pages with unscalable viewports shouldn't have a single tap delay(from iOS 9.3 onwards)
what about accessibility?
Chrome: Settings > Accessibility > Force enable zoom
Opera: Settings > Force enable zoom
Firefox: Settings > Accessibility > Always enable zoom
Samsung Internet: Internet settings > Manual zoom
"Force enable zoom" reintroduces delay – a fair compromise?patrickhlauke.github.io/touch/tests/event-listener_user-scalable-no.html
@thomasfuchs - Safari/iOS10beta3 ignores unscalable viewports(no official Apple documentation about the change...but the 300ms delay is back)
Windows 10 build 15007 on Mobile ignores unscalable viewports
"mobile optimised" viewportand
"double-tap to zoom"
Chrome 32+ / Android: content="width=device-width" suppresses double-tap-to-zoom, still allows pinch zoom
Google Developers: 300ms tap delay, gone away
Bug 941995 - Remove 300ms [...] on "responsive" pages[RESOLVED FIXED]
WebKit blog: More Responsive Tapping on iOS
patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay
suppressing 300ms delayif your code does rely on handling click / mouse events:
• "mobile optimised" <meta name="viewport"content="width=device-width">
• add touch-action:manipulation in CSS (part of Pointer Events)
• use helper library like fastclick.js for older browsers
• make your viewport non-scalable...
1. delayed event dispatch2. mousemove doesn't track
patrickhlauke.github.io/touch/particle/2
patrickhlauke.github.io/touch/particle/2
events fired on taptouchstart > [touchmove]+ > touchend >
(mouseenter) > mouseover > mousemove* > mousedown > (focus) >
mouseup > click* mouse event emulation fires only a single mousemove
too many touchmove events prevent mouse compatibility events after touchend
doubling up handling ofmousemove and touchmove
�ar posX, posY; function positionHandler(e) { posX = e.clientX ; posY = e.clientY ; } canvas.addEventListener(' mousemove ', positionHandler, false);
�ar posX, posY; function positionHandler(e) { posX = e.clientX ; posY = e.clientY ; } canvas.addEventListener(' mousemove ', positionHandler, false); canvas.addEventListener(' touchmove ', positionHandler, false); /* but this won't work for touch... */
interface MouseEvent : UIEvent { readonly attribute long screenX ; readonly attribute long screenY ; readonly attribute long clientX ; readonly attribute long clientY ; readonly attribute boolean ctrlKey; readonly attribute boolean shiftKey; readonly attribute boolean altKey; readonly attribute boolean metaKey; readonly attribute unsigned short button; readonly attribute EventTarget relatedTarget; // [DOM4] UI Events readonly attribute unsigned short buttons; };
www.w3.org/TR/DOM-Level-2-Events/events.html#Events-MouseEventwww.w3.org/TR/uievents/#events-mouseevents
partial interface MouseEvent { readonly attribute double screenX; readonly attribute double screenY; readonly attribute double pageX ; readonly attribute double pageY ; readonly attribute double clientX; readonly attribute double clientY; readonly attribute double x ; readonly attribute double y ; readonly attribute double offsetX ; readonly attribute double offsetY ; };
www.w3.org/TR/cssom-view/#extensions-to-the-mouseevent-interface
interface TouchEvent : UIEvent { readonly attribute TouchList touches ; readonly attribute TouchList targetTouches ; readonly attribute TouchList changedTouches ; readonly attribute boolean altKey; readonly attribute boolean metaKey; readonly attribute boolean ctrlKey; readonly attribute boolean shiftKey; };
www.w3.org/TR/touch-events/#touchevent-interface
interface Touch { readonly attribute long identifier; readonly attribute EventTarget target; readonly attribute long screenX ; readonly attribute long screenY ; readonly attribute long clientX ; readonly attribute long clientY ; readonly attribute long pageX ; readonly attribute long pageY ; };
www.w3.org/TR/touch-events/#touch-interface
TouchList differencestouches
all touch points on screen
targetTouchesall touch points that started on the element
changedTouchestouch points that caused the event to fire
patrickhlauke.github.io/touch/touchlist-objects
�ar posX, posY; function positionHandler(e) { if ((e.clientX)&&(e.clientY)) { posX = e.clientX; posY = e.clientY; } else if (e.targetTouches) { posX = e.targetTouches[0].clientX; posY = e.targetTouches[0].clientY; e.preventDefault() ; } } canvas.addEventListener('mousemove', positionHandler, false ); canvas.addEventListener('touchmove', positionHandler, false );
patrickhlauke.github.io/touch/particle/3
patrickhlauke.github.io/touch/paranoid_0.5www.splintered.co.uk/experiments/archives/paranoid_0.5
patrickhlauke.github.io/touch/picture-slider
tracking finger movement overtime ... swipe gestures
patrickhlauke.github.io/touch/swipe
/* Swipe detection from basic principles */ Δt = end.time - start.time; Δx = end.x - start.x; Δy = end.y - start.y; if (( Δt > timeThreshold ) || ( (Δx + Δy) < distanceThreshold )) { /* too slow or movement too small */ } else { /* it's a swipe! - use �x and �y to determine direction - pythagoras √( �x² + �y² ) for distance - distance/�t to determine speed */ }
don't forget mouse/keyboard!
touchmove fires...a lot!
do absolute minimum on eachtouchmove
(usually: store coordinates)
do heavy lifting (drawing etc.)separately, avoid queueing
(e.g. using setTimeout and/or requestAnimationFrame )
debounce / throttle events
GitHub: m-gagne / limit.js
patrickhlauke.github.io/touch/touch-limit
why stop at a single point? multitouch support
interface TouchEvent : UIEvent { readonly attribute TouchList touches ; readonly attribute TouchList targetTouches ; readonly attribute TouchList changedTouches ; readonly attribute boolean altKey; readonly attribute boolean metaKey; readonly attribute boolean ctrlKey; readonly attribute boolean shiftKey; };
www.w3.org/TR/touch-events/#touchevent-interface
/* iterate over relevant TouchList */ for (i=0; i< e.targetTouches .length; i++) { ... posX = e.targetTouches[i].clientX ; posY = e.targetTouches[i].clientY ; ... }
patrickhlauke.github.io/touch/tracker/multi-touch-tracker.html
iOS/iPad preventDefault()can't override 4-finger gestures
iOS7+ Safari/WebViewpreventDefault() can't
override edge swipes
multitouch gestures
/* iOS/Safari/WebView has gesture events for size/rotation, not part of the W3C Touch Events spec. */ /* gesturestart / gesturechange / gestureend */ foo.addEventListener('gesturechange', function(e) { /* e.scale e.rotation */ /* values can be plugged directly into CSS transforms etc */ }); /* not supported in Chrome/Firefox/Opera */
iOS Developer Library - Safari Web Content Guide - Handling gesture events
/* Pinch/rotation detection from basic principles */ Δx = x2 - x1; Δy = y2 - y1;
/* pythagoras √( �x² + �y² ) to calculate distance */ Δd = Math.sqrt( (Δx * Δx) + (Δy * Δy) );
/* trigonometry to calculate angle */ α = Math.atan2( Δy, Δx );
Mozilla Developer Network: Math.atan2()
patrickhlauke.github.io/touch/picture-organiser
Touch Events specification grey areas...
do touch events fire duringscroll/zoom?
not defined in spec (yet), but de facto yes in most modern browsers
patrickhlauke.github.io/touch/gesture-touch
Touch Events extensions...
W3C Touch Events Extensions WG Note
/* Extension to touch objects */ partial interface Touch { readonly attribute float radiusX; readonly attribute float radiusY; readonly attribute float rotationAngle; readonly attribute float force; };
/* Touch Events – contact geometry */ partial interface Touch { readonly attribute float radiusX ; readonly attribute float radiusY ; readonly attribute float rotationAngle ; readonly attribute float force; };
patrickhlauke.github.io/touch/tracker/tracker-radius-rotationangle.html“ouTube: Touch Events: radiusX, radius“ and rotationAngle
/* Touch Events – force */ partial interface Touch { readonly attribute float radiusX; readonly attribute float radiusY; readonly attribute float rotationAngle; readonly attribute float force ; };
force : value in range 0 – 1 . if no hardware support 0 (some devices, e.g. Nexus 10, "fake" force based on radiusX / radiusY )
patrickhlauke.github.io/touch/tracker/tracker-force-pressure.htmliPhone 6s with 3D Touch supports force ...
(Safari and WKWebView, e.g. Chrome/iOS, but not UIWebView, e.g. Firefox/iOS)
W3C Touch Events Level 2 (Editor's Draft)(merges errata, touch events extensions, fractional touch coordinates)
Pointer Events
up to IE9 (Win7 / WinPhone7.5)only mouse events
in IE10 Microsoft introducedPointer Events
unifies mouse, touch and pen input into a single event model
...and some new inputs (though currently mapped to mouse)Building Xbox One Apps using HTML and JavaScript
“ouTube: Xbox One Edge Browser sends Pointer Events
not just some not invented here
technology
submitted by Microsoft as W3C Candidate REC 09 May 2013
Pointer Events - W3C REC 24 February 2015
work now continues to enhance/expand Pointer Events...W3C Pointer Events Level 2 (Editor's Draft)
caniuse.com: Can I use pointer events?
Bug 822898 - Implement pointer events
about:config � dom.w3c_pointer_events.enabled
...what about Apple?
Microsoft submitted a proof of concept WebKit patchhtml5labs.interoperabilitybridges.com/prototypes/...
Bug 105463 - Implement pointer events RESOLVED WONTFIX
Maciej Stachowiak - [webkit-dev] pointer events specification - first editors draft
@patrick_h_lauke paraphrasing Apple's stance on Pointer Events...
Apple Pencil currentlyindistinguishable from touch
in browser / JavaScript (no tilt information, fires touch events)
the anatomy of Pointer Events (sequence, event object, ...)
patrickhlauke.github.io/touch/tests/event-listener_all-no-timings.html
events fired on tap (Edge)mousemove* >
pointerover > mouseover > pointerenter > mouseenter > pointerdown > mousedown >
focus gotpointercapture >
pointermove > mousemove > pointerup > mouseup > lostpointercapture >
click > pointerout > mouseout > pointerleave > mouseleave
mouse events fired inline with pointer events (for a primary pointer, e.g. first finger on screen)
IE10/IE11 quirks• vendor-prefixed in IE10 ( MSPointerDown ...,
navigator.msMaxTouchPoints , -ms-touch-action )
• unprefixed in IE11 (but prefixed versions mapped for compatibility)
• event order (when click is fired) incorrect in IE10/IE11
see W3C Pointer Events WG mailing list - Jacob Rossi (Microsoft)
Chrome, Edge (on mobile), IE11 (Windows Phone 8.1update1) support both Touch Events and Pointer Events
w3c.github.io/pointerevents/#mapping-for-devices-that-do-not-support-hover
patrickhlauke.github.io/touch/tests/event-listener_all-no-timings.html
about:flags in Microsoft Edge to turn on touch events on desktop(e.g. touch-enabled laptops) – off by default for site compatibility
... when touch events alsosupported (Edge)
pointerover > pointerenter > pointerdown > touchstart > pointerup > touchend >
mouseover > mouseenter > mousemove > mousedown > focus > mouseup > click >
pointerout > pointerleaveSpecific order of events is not defined in the spec in this case – will vary between browsers...
only problem if handling both pointer events and mouse events (which is nonsensical)
/* Pointer Events extend Mouse Events vs Touch Events and their new objects / TouchLists / Touches */ interface PointerEvent : MouseEvent { readonly attribute long pointerId; readonly attribute long width; readonly attribute long height; readonly attribute float pressure; readonly attribute float tangentialPressure; /* Level 2 */ readonly attribute long tiltX; readonly attribute long tiltY; readonly attribute long twist; /* Level 2 */ readonly attribute DOMString pointerType; readonly attribute boolean isPrimary; }
/* plus all MouseEvent attributes: clientX , clientY , etc */
handling mouse input isexactly the same as traditional
mouse events (only change pointer* instead of mouse* event names)
handling touch or stylus isalso exactly the same astraditional mouse events
(mouse code can be adapted to touch/stylus quickly)
simple feature detection forpointer events
/* detecting pointer events support */ if ( window.PointerEvent ) { /* some clever stuff here but this covers touch, stylus, mouse, etc */ } /* still listen to click for keyboard! */
"don't forget about keyboard users" note in Pointer Events spec
/* detect maximum number of touch points */ if ( navigator.maxTouchPoints > 0 ) { /* device with a touchscreen */ } if ( navigator.maxTouchPoints > 1 ) { /* multitouch-capable device */ }
"you can detect a touchscreen" ...but user may still use other input mechanisms
patrickhlauke.github.io/touch/tests/pointer-multitouch-detect.html
do pointer events fire duringscroll/zoom?
w3c.github.io/pointerevents/#the-pointercancel-event
once a browser handles scrolling, it sends pointercancelpatrickhlauke.github.io/touch/gesture-touch/pointerevents.html
pointer events vs
limitations/problems of mouseevent emulation
1. delayed event dispatch2. mousemove doesn't track
1. delayed event dispatch2. mousemove doesn't track
patrickhlauke.github.io/touch/tests/event-listener.html
(IE11/WinPhone 8.1 Update no optimization for width=device-width )
patrickhlauke.github.io/touch/tests/event-listener.html(IE/Win8 has double-tap to zoom, so problem on desktop too)
patrickhlauke.github.io/touch/tests/event-listener.html(Microsoft Edge/Win10 has double-tap to zoom, so problem on desktop too)
pointer / mouse events and delay
[300ms delay] click ...
300ms delay just before click event
how can we make it feelresponsive like a native app?
we could try a similarapproach to touch events...
• double-up pointerup and click listeners?
• prevent code firing twice with preventDefault ?
won't work: preventDefault() stops mouse compatibility events, butclick is not considered mouse compatibility event
a more declarative approach with touch-action
CSS propertywhat action should the browser handle?
touch-action: auto | none | [ pan-x || pan-y ] | manipulationwww.w3.org/TR/pointerevents/#the-touch-action-css-property
only determines default touch action, does not stop compatibilitymouse events nor click
Pointer Events Level 2expanded set of values (useful for pull-to-refresh, carousels, etc)
touch-action: auto | none | [ [ pan-x | pan-left | pan-right ] || [ pan-y | pan-up | pan-down ] ] | manipulation
w3c.github.io/pointerevents/#the-touch-action-css-property
compat.spec.whatwg.org add extra value pinch-zoom
patrickhlauke.github.io/touch/touch-action-scrolling
touch-action:none(suppress all default browser behaviour)
patrickhlauke.github.io/touch/tests/event-listener_touch[...]
touch-action:none killsscrolling, long-press,
pinch/zoom
touch-action:manipulation(suppress double-tap-to-zoom)
patrickhlauke.github.io/touch/tests/event-listener_touch[...]
caniuse.com: Can I use touch-action?
browsers working to removedouble-tap to zoom delay
(when page not zoomable)
<meta name="viewport" content="user-scalable=no">patrickhlauke.github.io/touch/tests/event-listener_user-scalable-no.html
"Allow zooming on all web content" reintroduces delaypatrickhlauke.github.io/touch/tests/event-listener_user-scalable-no.html
"Allow zooming..." option currently missing in Win 10 Mobile
Windows 10 build 15007 on Mobile ignores unscalable viewportsno delay until user zooms for first time...
width=device-width still has delay in IE11/WinPhone 8.1 Updatepatrickhlauke.github.io/touch/tests/event-listener_width-device-width.html
Microsoft Edge removes delay for width=device-widthpatrickhlauke.github.io/touch/tests/event-listener_width-device-width.html
patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay
1. delayed event dispatch2. mousemove doesn't track
just listen to pointermove ...
no need for separate mouse ortouch event listeners
/* touch events: separate handling */ foo.addEventListener('touchmove', ... , false); foo.addEventListener('mousemove', ... , false);
/* pointer events: single listener for mouse, stylus, touch */ foo.addEventListener(' pointermove ', ... , false);
no need for separate mouse ortouch code to get x / y coords
/* Reminder: Touch Events need separate code for x / y coords */ function positionHandler(e) { if ((e.clientX)&&(e.clientY)) { posX = e.clientX; posY = e.clientY; } else if (e.targetTouches) { posX = e.targetTouches[0].clientX; posY = e.targetTouches[0].clientY; ... } } canvas.addEventListener('mousemove', positionHandler, false ); canvas.addEventListener('touchmove', positionHandler, false );
/* Pointer Events extend Mouse Events */ foo.addEventListener(' pointermove ', function(e) { ... posX = e.clientX ; posY = e.clientY ; ... }, false);
www.w3.org/TR/pointerevents/#pointerevent-interface
3D Rotator by Creative Punchcoded to only use mouse events
3D Rotator modified to use Pointer Eventsminimal code changes, as Pointer Events extend mouse events
but you can distinguish mouse or touch or stylus
foo.addEventListener('pointermove', function(e) { ... switch( e.pointerType ) { case ' mouse ': ... break; case ' pen ': ... break; case ' touch ': ... break; default : /* future-proof */ } ... } , false);
what about multitouch?
/* PointerEvents don't have the handy TouchList objects, so we have to replicate something similar... */ ar points = []; switch (e.type) { case ' pointerdown ': /* add to the array */ break; case ' pointermove ': /* update the relevant array entry's x and y */ break; case ' pointerup ': case ' pointercancel ': /* remove the relevant array entry */ break; }
patrickhlauke.github.io/touch/tracker/multi-touch-tracker-pointer-hud.html(note multiple isPrimary pointers, per pointer type)
/* like iOS/Safari, IE/Win has higher-level gestures , but these are not part of the W3C Pointer Events spec. Replicate these from basic principles again... */
MSDN IE10 Developer Guide: Gesture object and events
extended capabilities (if supported by hardware)
/* Pointer Events - pressure */ interface PointerEvent : MouseEvent { readonly attribute long pointerId; readonly attribute long width; readonly attribute long height; readonly attribute float pressure ; readonly attribute float tangentialPressure; readonly attribute long tiltX; readonly attribute long tiltY; readonly attribute long twist; readonly attribute DOMString pointerType; readonly attribute boolean isPrimary; }
pressure : value in range 0 – 1 . if no hardware support, 0.5 in active button state, 0 otherwise
patrickhlauke.github.io/touch/tracker/...“ouTube: Touch tracker with Surface 3 pen
hovering stylus• hardware-dependant
• pointermove fires
• pressure == 0 (non-active button state)
• track pointerdown / pointerup to be safe
/* Pointer Events - contact geometry */ interface PointerEvent : MouseEvent { readonly attribute long pointerId; readonly attribute long width ; readonly attribute long height ; readonly attribute float pressure; readonly attribute float tangentialPressure; readonly attribute long tiltX; readonly attribute long tiltY; readonly attribute long twist; readonly attribute DOMString pointerType; readonly attribute boolean isPrimary; }
if hardware can't detect contact geometry, either 0 or "best guess" (e.g. for mouse/stylus, return width / height of 1 )
patrickhlauke.github.io/touch/tracker/tracker-width-height.html“ouTube: Pointer Events width and height ...
/* Pointer Events - tilt */ interface PointerEvent : MouseEvent { readonly attribute long pointerId; readonly attribute long width; readonly attribute long height; readonly attribute float pressure; readonly attribute float tangentialPressure; readonly attribute long tiltX ; readonly attribute long tiltY ; readonly attribute long twist; readonly attribute DOMString pointerType; readonly attribute boolean isPrimary; }
tiltX / tiltY : value in degrees -90 – 90 . returns 0 if hardware does not support tilt
patrickhlauke.github.io/touch/pen-tracker“ouTube: ...pen with tilt, pressure and hover support
patrickhlauke.github.io/touch/pen-tracker“ouTube: Chrome on Samsung Galaxy Note 4 - Pointer Events and stylus
pointermove fires if anyproperty changes,
not just x/y position ( width , height , tiltX , tiltY , pressure )
pointer events as the future?
transitional event handling (until all browsers support pointer events)
/* cover all cases (hat-tip Stu Cox) */ if (window.PointerEvent) { /* bind to Pointer Events: pointerdown, pointerup, etc */ } else { /* bind to mouse events: mousedown, mouseup, etc */ if ('ontouchstart' in window) { /* bind to Touch Events: touchstart, touchend, etc */ } } /* bind to keyboard / click */
polyfills for pointer events (code for tomorrow, today)
GitHub - jQuery Pointer Events Polyfill (PEP)
�� adding jQuery PEP *� <script src="https:��code.jquery.com�pep�0.4.1�pep.js"><�script> �* need to use custom touch-action attribute, not CSS (yet) *� <button touch-action="none" >...<�div>
patrickhlauke.github.io/touch/pep-draw
patrickhlauke.github.io/touch/pep/listener/event-listener.html
debugging/testing
nothing beats having real devices...
Chrome DevTools / Device Mode & Mobile Emulationcorrectly emulates touch and pointer events
Firefox Developer Tools > Responsive Design Modecorrectly emulates touch events
no touch emulation, nor touch events + pointer events (like on realWindows 10 Mobile) emulation, in Edge/F12 Tools
no touch emulation in Safari "Responsive Design Mode"
youtube.com/watch?v=A”KpByV5764
get in touch@patrick_h_lauke
github.com/patrickhlauke/touch patrickhlauke.github.io/getting-touchy-presentation
slideshare.net/redux paciellogroup.com
splintered.co.uk