使用 Hammer 和 Angular 8 在整个屏幕上捕获滑动事件
Capture swipe event on entire screen with Hammer and Angular 8
我正在尝试在我的应用程序的整个屏幕上捕捉滑动手势。这个想法是让其他服务可以收听这些调度操作,在本例中是用于导航目的的路由器。
因为我只想将这些侦听器放在一个地方,所以我尝试将它们附加到主体或 div 覆盖我的应用程序屏幕。这两种方法都不如我所愿。
<div (swipeleft)="swipeLeft()" (swiperight)="swipeRight()" class="touch"></div>
swipeLeft() {
this.store.dispatch(UserActions.swipeLeft());
}
回想起来,触摸层的问题应该很明显:它覆盖了屏幕,因此覆盖了应用程序的其余部分。设置 pointer-events: none;
到达应用程序的其余部分会中断滑动检测。
const mc = new Hammer(document.querySelector('body'));
mc.on('swipeleft swiperight', (ev) => {
console.log(ev.type);
// this.store.dispatch(UserActions.swipeLeft());
});
在这里附加它的问题是它似乎只在某些元素上注册滑动,比如 app-root
和我有的状态栏,但不在我的路由器插座上,也不在底部的工具栏上拿着一些按钮。
那么,如何在我的整个应用程序上捕获滑动?
我试图创建一个片段来重现该问题,但没有 Angular 组件,它的行为几乎与我希望我的应用程序的行为一样。尝试从代码段中的按钮边缘滑动时,可以观察到与我的问题类似的行为。
const touchLayer = document.getElementById('touch');
const body = document.querySelector('body');
const mc = new Hammer(body);
mc.on("swipeleft swiperight", function(ev) {
touchLayer.textContent = ev.type + " gesture detected.";
});
#touch,
#myApp {
position: fixed;
height: 300px;
width: 100%;
}
#myApp {
background: repeating-linear-gradient(-55deg, #666, #666 10px, #333 10px, #333 20px);
opacity: .5;
}
#touch {
background: cyan;
text-align: center;
font: 30px/300px Helvetica, Arial, sans-serif;
opacity: .5;
}
.card {
width: 200px;
height: 100px;
background: red;
position: relative;
margin: 1em;
}
button {
margin: 2em;
right: 0;
bottom: 0;
position: absolute;
}
<script src="https://hammerjs.github.io/dist/hammer.js"></script>
<!-- Tried putting this on top, blocking the screen -->
<div id="touch"></div>
<div id="myApp">
<div class="card">
<button onclick="alert('test')">Button!</button>
</div>
<div class="card">
<button onclick="alert('test')">Button!</button>
</div>
</div>
当您想将 Hammer 添加到 Angular 8 应用程序时,您需要作为提供者 HAMMER_GESTURE_CONFIG 并使用 class HammerGestureConfig
providers: [
{
provide: HAMMER_GESTURE_CONFIG,
useClass: HammerGestureConfig
}
]
好吧,如果你想使用另一个 class thar override some propertie -e.g.你想在所有方向滑动-,你创建一个扩展 HammerGestureConfig 的 class 并在 provider
中使用这个 class
export class MyHammerConfig extends HammerGestureConfig {
overrides = <any>{
swipe: { direction: Hammer.DIRECTION_ALL }
};
}
// And use as provider
providers: [
{
provide: HAMMER_GESTURE_CONFIG,
useClass: MyHammerConfig
}
]
在您的应用中,您可以使用 fromEvent rxjs
const hammerConfig = new HammerGestureConfig()
//or if you use another class as provider:
// const hammerConfig=new MyHammerConfig()
const hammer=hammerConfig.buildHammer(document.documentElement)
fromEvent(hammer, "swipe").pipe(
takeWhile(()=>this.alive))
.subscribe((res: any) => {
console.log(res.deltaX);
});
请参阅 stackblitz
中的示例
(*)我放了一个管道 takeWhile 来备注必要的退订
我正在尝试在我的应用程序的整个屏幕上捕捉滑动手势。这个想法是让其他服务可以收听这些调度操作,在本例中是用于导航目的的路由器。
因为我只想将这些侦听器放在一个地方,所以我尝试将它们附加到主体或 div 覆盖我的应用程序屏幕。这两种方法都不如我所愿。
<div (swipeleft)="swipeLeft()" (swiperight)="swipeRight()" class="touch"></div>
swipeLeft() {
this.store.dispatch(UserActions.swipeLeft());
}
回想起来,触摸层的问题应该很明显:它覆盖了屏幕,因此覆盖了应用程序的其余部分。设置 pointer-events: none;
到达应用程序的其余部分会中断滑动检测。
const mc = new Hammer(document.querySelector('body'));
mc.on('swipeleft swiperight', (ev) => {
console.log(ev.type);
// this.store.dispatch(UserActions.swipeLeft());
});
在这里附加它的问题是它似乎只在某些元素上注册滑动,比如 app-root
和我有的状态栏,但不在我的路由器插座上,也不在底部的工具栏上拿着一些按钮。
那么,如何在我的整个应用程序上捕获滑动?
我试图创建一个片段来重现该问题,但没有 Angular 组件,它的行为几乎与我希望我的应用程序的行为一样。尝试从代码段中的按钮边缘滑动时,可以观察到与我的问题类似的行为。
const touchLayer = document.getElementById('touch');
const body = document.querySelector('body');
const mc = new Hammer(body);
mc.on("swipeleft swiperight", function(ev) {
touchLayer.textContent = ev.type + " gesture detected.";
});
#touch,
#myApp {
position: fixed;
height: 300px;
width: 100%;
}
#myApp {
background: repeating-linear-gradient(-55deg, #666, #666 10px, #333 10px, #333 20px);
opacity: .5;
}
#touch {
background: cyan;
text-align: center;
font: 30px/300px Helvetica, Arial, sans-serif;
opacity: .5;
}
.card {
width: 200px;
height: 100px;
background: red;
position: relative;
margin: 1em;
}
button {
margin: 2em;
right: 0;
bottom: 0;
position: absolute;
}
<script src="https://hammerjs.github.io/dist/hammer.js"></script>
<!-- Tried putting this on top, blocking the screen -->
<div id="touch"></div>
<div id="myApp">
<div class="card">
<button onclick="alert('test')">Button!</button>
</div>
<div class="card">
<button onclick="alert('test')">Button!</button>
</div>
</div>
当您想将 Hammer 添加到 Angular 8 应用程序时,您需要作为提供者 HAMMER_GESTURE_CONFIG 并使用 class HammerGestureConfig
providers: [
{
provide: HAMMER_GESTURE_CONFIG,
useClass: HammerGestureConfig
}
]
好吧,如果你想使用另一个 class thar override some propertie -e.g.你想在所有方向滑动-,你创建一个扩展 HammerGestureConfig 的 class 并在 provider
中使用这个 classexport class MyHammerConfig extends HammerGestureConfig {
overrides = <any>{
swipe: { direction: Hammer.DIRECTION_ALL }
};
}
// And use as provider
providers: [
{
provide: HAMMER_GESTURE_CONFIG,
useClass: MyHammerConfig
}
]
在您的应用中,您可以使用 fromEvent rxjs
const hammerConfig = new HammerGestureConfig()
//or if you use another class as provider:
// const hammerConfig=new MyHammerConfig()
const hammer=hammerConfig.buildHammer(document.documentElement)
fromEvent(hammer, "swipe").pipe(
takeWhile(()=>this.alive))
.subscribe((res: any) => {
console.log(res.deltaX);
});
请参阅 stackblitz
中的示例(*)我放了一个管道 takeWhile 来备注必要的退订