-
-
Save SleepWalker/da5636b1abcbaff48c4d to your computer and use it in GitHub Desktop.
var touchstartX = 0; | |
var touchstartY = 0; | |
var touchendX = 0; | |
var touchendY = 0; | |
var gesuredZone = document.getElementById('gesuredZone'); | |
gesuredZone.addEventListener('touchstart', function(event) { | |
touchstartX = event.screenX; | |
touchstartY = event.screenY; | |
}, false); | |
gesuredZone.addEventListener('touchend', function(event) { | |
touchendX = event.screenX; | |
touchendY = event.screenY; | |
handleGesure(); | |
}, false); | |
function handleGesure() { | |
var swiped = 'swiped: '; | |
if (touchendX < touchstartX) { | |
alert(swiped + 'left!'); | |
} | |
if (touchendX > touchstartX) { | |
alert(swiped + 'right!'); | |
} | |
if (touchendY < touchstartY) { | |
alert(swiped + 'down!'); | |
} | |
if (touchendY > touchstartY) { | |
alert(swiped + 'left!'); | |
} | |
if (touchendY == touchstartY) { | |
alert('tap!'); | |
} | |
} |
I guess he means it will trigger multiple conditions, you can check which direction has the most bias:
let startX = 0;
let startY = 0;
function handleTouchStart(e) {
startX = e.changedTouches[0].screenX;
startY = e.changedTouches[0].screenY;
}
function handleTouchEnd(e) {
const diffX = e.changedTouches[0].screenX - startX;
const diffY = e.changedTouches[0].screenY - startY;
const ratioX = Math.abs(diffX / diffY);
const ratioY = Math.abs(diffY / diffX);
const absDiff = Math.abs(ratioX > ratioY ? diffX : diffY);
// Ignore small movements.
if (absDiff < 30) {
return;
}
if (ratioX > ratioY) {
if (diffX >= 0) {
console.log('right swipe');
} else {
console.log('left swipe');
}
} else {
if (diffY >= 0) {
console.log('down swipe');
} else {
console.log('up swipe');
}
}
}
hello people, the 0 in the changedTouches property stands for the number of touches i guess, meaning the number of fingers needed to detect the event? please help, i cannot find proper answers online (Or at least answers i understand...)...
Thanks
I guess he means it will trigger multiple conditions, you can check which direction has the most bias:
let startX = 0; let startY = 0; function handleTouchStart(e) { startX = e.changedTouches[0].screenX; startY = e.changedTouches[0].screenY; } function handleTouchEnd(e) { const diffX = e.changedTouches[0].screenX - startX; const diffY = e.changedTouches[0].screenY - startY; const ratioX = Math.abs(diffX / diffY); const ratioY = Math.abs(diffY / diffX); const absDiff = Math.abs(ratioX > ratioY ? diffX : diffY); // Ignore small movements. if (absDiff < 30) { return; } if (ratioX > ratioY) { if (diffX >= 0) { console.log('right swipe'); } else { console.log('left swipe'); } } else { if (diffY >= 0) { console.log('down swipe'); } else { console.log('up swipe'); } } }
hello, I tried to use your answer and make simple func for that. Also want to make it for only swipe left. Any help?
I tried this and error.
function swipe(e) {
handleTouchStart(e);
handleTouchEnd(e);
}
let e = document.querySelector('.nbr');swipe(e);
I have a quite lengthy solution that handles touchstart, touchmove, and touchend events alone. ~100 lines of code (minus comments).
This solution also returns the amount of pixels swiped, useful for creating a carousel or a swipeable component.
The code is below, you can modify it and get rid of what you don't need.
//to check that it's the right direction.
const log = x => console.log(x)
class RootSwipeable {
//offset is amount of pixels swiped to be considered a direction.
//else multiple directions might trigger at once.
constructor({ offset }) {
this.offset = offset
this.previous = { x: null, y: null }
}
updatePrevious(e) {
this.previous.x = e.changedTouches[0].screenX
this.previous.y = e.changedTouches[0].screenY
}
init(e) {
!this.previous.x && !this.previous.y
&& this.updatePrevious(e);
}
handleGesture(e, {
onLeft = () => { },
onRight = () => { },
onUp = () => { },
onDown = () => { } })
{
let screenX = e.changedTouches[0].screenX,
screenY = e.changedTouches[0].screenY;
if (this.previous.x + this.offset < screenX) {
log('right')
this.updatePrevious(e)
onRight()
return
}
if (this.previous.x - this.offset > screenX) {
log('left')
this.updatePrevious(e)
onLeft()
return
}
if (this.previous.y + this.offset < screenY) {
log('down')
this.updatePrevious(e)
onDown()
return
}
if (this.previous.y - this.offset > screenY) {
log('up')
this.updatePrevious(e)
onUp()
return
}
}
kill() { this.previous = { x: null, y: null } }
}
//edited "c7x43t's" code above...
//main method.
export default class Swipeable {
constructor({ offset }) {
this.root = new RootSwipeable({ offset })
this.pageWidth = window.innerWidth || document.body.clientWidth
this.threshold = Math.max(1, Math.floor(0.01 * (this.pageWidth)))
this.touchstart = { x: 0, y: 0 }
this.touchend = { x: 0, y: 0 }
this.limit = Math.tan(45 * 1.5 / 180 * Math.PI)
}
touchStart(e) {
root.init(e)
this.touchstart.x = e.changedTouches[0].screenX
this.touchstart.y = e.changedTouches[0].screenY
}
touchMove(e, {
onLeft = () => { },
onRight = () => { },
onUp = () => { },
onDown = () => { }
}) {
this.touchend.x = e.changedTouches[0].screenX;
this.touchend.y = e.changedTouches[0].screenY;
this.handleGesture(e, { onLeft, onRight, onUp, onDown })
}
handleGesture(e, { onLeft, onRight, onUp, onDown }) {
let x = this.touchend.x - this.touchstart.x,
y = this.touchend.y - this.touchstart.y;
if (Math.abs(x) > this.threshold || Math.abs(y) > this.threshold) {
root.handleGestures(e, {
onUp: () => onUp(e, y),
onRight: () => onRight(e, x),
onDown: () => onDown(e, y),
onLeft: () => onLeft(e, x)
})
//root.handleGestures() is the initial root class above.//
}
}
touchEnd() {
root.kill()
this.touchstart = { x: 0, y: 0 }
this.touchend = { x: 0, y: 0 }
}
}
The module above will then be used as so
import Swipeable from '@file_location'
//offset is preferably a number >= 2 && <= 10.
const swipeable = new Swipeable({ offset: 2 })
//example component: carousel//
document.querySelector('.carousel').addEventListener('touchstart', e => swipeable.touchStart(e))
document.querySelector('.carousel').addEventListener('touchmove', e => {
swipeable.touchMove(e, { onUp: (e, x) => console.log(e, x + 'px swiped') })
})
document.querySelector('.carousel').addEventListener('touchend', e => swipeable.touchEnd(e))
Works great, thanks!
This is starting to look like one of the leading script threads on vanillaJS touch events. Seems like Hammer, Zing and Interactjs (pointer events) libs (interact excluded) are maybe become a bit obsolete except for drag, drop, and pointer support. Does anyone have any flushed out changes they have made since (as the thread goes back a few years)? Would be cool to keep this thread up to date with any changes or learnings. Anyone using this extensively with event listeners on touchMove? @evrenakar @tlacaelelrl @hperrin
Despite not doing any work on it in a couple years, I still do maintain and use my version with the additional features I mentioned:
https://github.com/sciactive/tinygesture
For anyone still interesting, I just made a bit modified version to get swipe gesture controls on in-browser explorers.
let touchstartX = 0;
let touchstartY = 0;
let touchendX = 0;
let touchendY = 0;
function handleGesture(touchstartX, touchstartY, touchendX, touchendY) {
const delx = touchendX - touchstartX;
const dely = touchendY - touchstartY;
if(Math.abs(delx) > Math.abs(dely)){
if(delx > 0) return "right"
else return "left"
}
else if(Math.abs(delx) < Math.abs(dely)){
if(dely > 0) return "down"
else return "up"
}
else return "tap"
}
const gestureZone = document.getElementById('main');
gestureZone.addEventListener('touchstart', function(event) {
touchstartX = event.changedTouches[0].screenX;
touchstartY = event.changedTouches[0].screenY;
}, false);
gestureZone.addEventListener('touchend', function(event) {
touchendX = event.changedTouches[0].screenX;
touchendY = event.changedTouches[0].screenY;
alert(handleGesture(touchstartX, touchstartY, touchendX, touchendY))
}, false);
The source thread requires ultra precise swipes
Ohh, yes. Your solution is a acting up on FF but it is the most elegant. Will do more testing.
Thank you, works fine for me!
Quick dumb question, how do you write a function to count the number of swipes to the left or right?
@jonseo I'd probably just create a variable or variables outside of the addEventListener scope (so basically just at the top of the code) and then increment those inside the addEventListener function
lmk if that's too brief a description
Yeh, thats a bit brief, can u point me to some code examples. much appreciated.
@jonseo check this https://gist.github.com/SleepWalker/da5636b1abcbaff48c4d?permalink_comment_id=3537435#gistcomment-3537435
especially
document.querySelector('.carousel').addEventListener('touchmove', e => {
swipeable.touchMove(e, {
onUp: (e, x) => console.log(e, x + 'px swiped') ,
onLeft: (e, x) => console.log(e, x + 'px swiped')
})
})
I hope that's what you mean
thnk you!
Great, but still have questions about different browser compatibility issues.
What did you change @vwebtech ?