Detecting a swipe (left, right, top or down) using touch
Swiping in touch is the act of quickly moving your finger
across the touch surface in a certain direction. There is currently no "onswipe
" event
in JavaScript, which means it's up to us to implement one using the
available touch events, plus define just when a swipe is a, well, "swipe".
Lets first define when a movement across the touch surface
should be considered a swipe. There are two variables at play here- the
distance traveled by the user's finger on the x or y-axis from touchstart
to
touchend
, and, the time it took. Based on these two factors, we can decide
whether that action qualifies as a swipe and in what direction.
With that said, lets put ideas into action and see how to go about detecting a swipe right (from left to right). Once we can do that, detecting swipe in the other 3 directions is pretty much identical. For this exercise we'll stipulate that a right swipe has occurred when the user has moved his finger across the touch surface a minimum of 150px horizontally in 200 ms or less from left to right. Furthermore, there should be no more than 100px traveled vertically, to avoid "false positives" whereby the user swipes diagonally across, which we don't want to qualify as a swipe right.
Example (mouse simulation added for non touch devices):
<script> window.addEventListener('load', function(){ var touchsurface = document.getElementById('touchsurface'), startX, startY, dist, threshold = 150, //required min distance traveled to be considered swipe allowedTime = 200, // maximum time allowed to travel that distance elapsedTime, startTime function handleswipe(isrightswipe){ if (isrightswipe) touchsurface.innerHTML = 'Congrats, you\'ve made a <span style="color:red">right swipe!</span>' else{ touchsurface.innerHTML = 'Condition for right swipe not met yet' } } touchsurface.addEventListener('touchstart', function(e){ touchsurface.innerHTML = '' var touchobj = e.changedTouches[0] dist = 0 startX = touchobj.pageX startY = touchobj.pageY startTime = new Date().getTime() // record time when finger first makes contact with surface e.preventDefault() }, false) touchsurface.addEventListener('touchmove', function(e){ e.preventDefault() // prevent scrolling when inside DIV }, false) touchsurface.addEventListener('touchend', function(e){ var touchobj = e.changedTouches[0] dist = touchobj.pageX - startX // get total dist traveled by finger while in contact with surface elapsedTime = new Date().getTime() - startTime // get time elapsed // check that elapsed time is within specified, horizontal dist traveled >= threshold, and vertical dist traveled <= 100 var swiperightBol = (elapsedTime <= allowedTime && dist >= threshold && Math.abs(touchobj.pageY - startY) <= 100) handleswipe(swiperightBol) e.preventDefault() }, false) }, false) // end window.onload </script> <div id="touchsurface">Swipe Me</div>
Inside touchend
, we check that the dist traveled from
touchstart
to touchend
is a positive number above the specified threshold
value (ie: 150), since in a right swipe, that dist should always be positive
based on the equation used (versus negative for a left swipe). At the same
time, we make sure any vertical lateral movement traveled is less than 100px
to weed out diagonal swipes. Since the vertical movement can occur either above
the starting touch point or below, we use Math.abs()
when getting the
absolute vertical dist traveled so both scenarios are covered when comparing it to our
vertical threshold value of 100.
A generic swipe detecting function
Now that we got right swipe down, lets create a more generic function that detects swiping in either of the 4 directions (left, right, up, or down):
function swipedetect(el, callback){ var touchsurface = el, swipedir, startX, startY, distX, distY, threshold = 150, //required min distance traveled to be considered swipe restraint = 100, // maximum distance allowed at the same time in perpendicular direction allowedTime = 300, // maximum time allowed to travel that distance elapsedTime, startTime, handleswipe = callback || function(swipedir){} touchsurface.addEventListener('touchstart', function(e){ var touchobj = e.changedTouches[0] swipedir = 'none' dist = 0 startX = touchobj.pageX startY = touchobj.pageY startTime = new Date().getTime() // record time when finger first makes contact with surface e.preventDefault() }, false) touchsurface.addEventListener('touchmove', function(e){ e.preventDefault() // prevent scrolling when inside DIV }, false) touchsurface.addEventListener('touchend', function(e){ var touchobj = e.changedTouches[0] distX = touchobj.pageX - startX // get horizontal dist traveled by finger while in contact with surface distY = touchobj.pageY - startY // get vertical dist traveled by finger while in contact with surface elapsedTime = new Date().getTime() - startTime // get time elapsed if (elapsedTime <= allowedTime){ // first condition for awipe met if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint){ // 2nd condition for horizontal swipe met swipedir = (distX < 0)? 'left' : 'right' // if dist traveled is negative, it indicates left swipe } else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint){ // 2nd condition for vertical swipe met swipedir = (distY < 0)? 'up' : 'down' // if dist traveled is negative, it indicates up swipe } } handleswipe(swipedir) e.preventDefault() }, false) } //USAGE: /* var el = document.getElementById('someel') swipedetect(el, function(swipedir){ swipedir contains either "none", "left", "right", "top", or "down" if (swipedir =='left') alert('You just swiped left!') }) */
swipedetect()
accepts two parameters, the element to bind
the touch events to, plus a function to execute when a swipe has occurred.
The function parameter "swipedir
" tells you the type of swipe that was just
made with five possible values: "none", "left", "right", "top", or "down".
The below uses the swipedetect()
function to show a "left", "right", "top", or "down"
background image (overlaid on top of a default background image) depending
on the swipe that has just occurred:
Example (mouse simulation added for non touch devices):
The code used is:
window.addEventListener('load', function(){ var el = document.getElementById('touchsurface2') var inner = document.getElementById('inner') var hidetimer = null swipedetect(el, function(swipedir){ if (swipedir != 'none'){ clearTimeout(hidetimer) var bgimage = swipedir + 'arrow.png' // naming convention is "leftarrow.png", "rightarrow.png" etc inner.style.background = 'transparent url(' + bgimage + ') center center no-repeat' hidetimer = setTimeout(function(){ // reset background image after 1 second inner.style.background = '' }, 1000) } }) }, false)
The HTML markup is:
<div id="touchsurface2"> <div id="inner"> Swipe Me </div> </div>
We bind swipedetect()
to "#touchsurface2
",
and whenever a valid swipe has occurred inside it, we change the "#inner
"
DIV's background image accordingly to reflect the type of swipe that has
just occurred.
- Introduction to Touch events in JavaScript
- Detecting a swipe using touch
- Monitoring touch actions at every stage, swipe image gallery
Monitoring touch actions at every stage, swipe image gallery