Angular 使用原生事件和 rxjs 滑动页面
Angular swipe pages with native events and rxjs
我想使用本机事件和 rxjs 在 angular 中的页面之间滑动。我找到 this 并更改了我的代码以使用 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');
}
});
}
然而,我在订阅中的函数被调用了多次,这意味着我的滑动从未被执行,因为我的 treshhold 0.3 * document.body.clientWidth
从未被满足。为了调试,我添加了以下代码:
fromEvent(document, 'touchend').subscribe((e) => {
console.log('test2');
});
然后我的控制台输出是这样的,显示 takeUntil
没有按预期工作:
test -24.941162109375
test -8
test -9.41180419921875
test -8.4705810546875
test -9.88232421875
test2
我在这里错过了什么?
此处 pairwise()
运算符的用法是错误的。根据您的预期排放量 [touchstartEvent, touchendEvent]
,pairwise()
并没有按照您认为的那样进行。发出的实际值是 [touchmove[0], touchmove[1]]
.
我建议如下
使用 zipWith
运算符合并 touchstart
和 touchend
并忽略 touchmove
如果它的值不是必需的。
在订阅回调中使用 return
来停止进一步执行对我来说并不优雅。您可以改为翻转 if
语句的条件。
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');
}
}
}
});
}
工作示例(触摸事件替换为鼠标事件):Stackblitz
不幸的是,Michaels 的回答只适用于鼠标事件,因为 endtouch 事件不包含 clientX 信息。
因此我调整了他的回答:
ngAfterViewInit(): void {
fromEvent<TouchEvent>(document, 'touchstart')
.pipe(
zipWith(
fromEvent<TouchEvent>(document, 'touchend').pipe(
withLatestFrom(fromEvent<TouchEvent>(document, 'touchmove'))
)
)
)
.subscribe(([touchstart, [_, touchmove]]) => {
const xDiff =
touchstart.touches[0].clientX - touchmove.touches[0].clientX;
console.log(xDiff);
if (Math.abs(xDiff) > 0.3 * document.body.clientWidth &&
touchstart.timeStamp <= touchmove.timeStamp) {
if (xDiff > 0) {
console.log('right swipe');
} else {
console.log('left swipe');
}
}
});
}
我想使用本机事件和 rxjs 在 angular 中的页面之间滑动。我找到 this 并更改了我的代码以使用 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');
}
});
}
然而,我在订阅中的函数被调用了多次,这意味着我的滑动从未被执行,因为我的 treshhold 0.3 * document.body.clientWidth
从未被满足。为了调试,我添加了以下代码:
fromEvent(document, 'touchend').subscribe((e) => {
console.log('test2');
});
然后我的控制台输出是这样的,显示 takeUntil
没有按预期工作:
test -24.941162109375
test -8
test -9.41180419921875
test -8.4705810546875
test -9.88232421875
test2
我在这里错过了什么?
此处 pairwise()
运算符的用法是错误的。根据您的预期排放量 [touchstartEvent, touchendEvent]
,pairwise()
并没有按照您认为的那样进行。发出的实际值是 [touchmove[0], touchmove[1]]
.
我建议如下
使用
zipWith
运算符合并touchstart
和touchend
并忽略touchmove
如果它的值不是必需的。在订阅回调中使用
return
来停止进一步执行对我来说并不优雅。您可以改为翻转if
语句的条件。
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');
}
}
}
});
}
工作示例(触摸事件替换为鼠标事件):Stackblitz
不幸的是,Michaels 的回答只适用于鼠标事件,因为 endtouch 事件不包含 clientX 信息。
因此我调整了他的回答:
ngAfterViewInit(): void {
fromEvent<TouchEvent>(document, 'touchstart')
.pipe(
zipWith(
fromEvent<TouchEvent>(document, 'touchend').pipe(
withLatestFrom(fromEvent<TouchEvent>(document, 'touchmove'))
)
)
)
.subscribe(([touchstart, [_, touchmove]]) => {
const xDiff =
touchstart.touches[0].clientX - touchmove.touches[0].clientX;
console.log(xDiff);
if (Math.abs(xDiff) > 0.3 * document.body.clientWidth &&
touchstart.timeStamp <= touchmove.timeStamp) {
if (xDiff > 0) {
console.log('right swipe');
} else {
console.log('left swipe');
}
}
});
}