'Angular swipe pages with native events and rxjs
I want to swipe between pages in angular using native events and rxjs. I found this and changed my code to work with rxjs:
ngAfterViewInit(): void {
fromEvent<TouchEvent>(document, 'touchstart')
.pipe(
switchMap(() =>
fromEvent<TouchEvent>(document, 'touchmove').pipe(
takeUntil(fromEvent(document, 'touchend')),
pairwise()
)
)
)
.subscribe(([touchstartEvent, touchendEvent]) => {
const xDiff =
touchstartEvent.touches[0].clientX - touchendEvent.touches[0].clientX;
console.log(xDiff);
if (Math.abs(xDiff) < 0.3 * document.body.clientWidth) {
return;
}
if (xDiff > 0) {
console.log('right swipe');
} else {
console.log('left swipe');
}
});
}
However my function in subscribe is called multiple times, which means my swipe is never executed because my treshhold 0.3 * document.body.clientWidth is never met. For debugging I added the following code:
fromEvent(document, 'touchend').subscribe((e) => {
console.log('test2');
});
Then my console output is something like this, showing takeUntil not working as expected:
test -24.941162109375
test -8
test -9.41180419921875
test -8.4705810546875
test -9.88232421875
test2
What am I missing here?
Solution 1:[1]
Usage of the pairwise() operator is wrong here. Based on your expected emission [touchstartEvent, touchendEvent], the pairwise() isn't doing what you think it's doing. The actual values getting emitted are [touchmove[0], touchmove[1]].
I'd propose the following
Use
zipWithoperator to mergetouchstartandtouchendand ignore thetouchmoveif it's value isn't required.Using
returninside the subscription callback to stop the further execution doesn't look elegant to me. You could instead flip the condition of theifstatement.
ngAfterViewInit(): void {
fromEvent<TouchEvent>(document, 'touchstart')
.pipe(zipWith(fromEvent<TouchEvent>(document, 'touchend')))
.subscribe({
next: ([touchstartEvent, touchendEvent]) => {
const xDiff =
touchstartEvent.touches[0].clientX - touchendEvent.touches[0].clientX;
console.log(xDiff);
if (Math.abs(xDiff) > 0.3 * document.body.clientWidth) {
if (xDiff > 0) {
console.log('right swipe');
} else {
console.log('left swipe');
}
}
}
});
}
Working example (touch events replaced with mouse events): Stackblitz
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ruth |
