我想要的
...是在Angular 9中使用Hammer.js检测平移(或滑动)。
它应该像这样工作:
- 应检测水平平移
- 应检测特定角度的对角线平移1
- 不应防止垂直滚动
- 不应防止捏合缩放,因为这会导致可访问性问题
在图片中, 绿色
表示默认的浏览器行为,不应被阻止。 蓝色
表示应该被防止并由Hammer处理的行为。
不确定我的意思?看看 Swiper
的演示。 它们的操作方式与此完全相同。
1 可以使用 event.angle
来检测角度。但我不确定如何区分是否必要时防止事件。
我尝试过的
...是我在Stackoverflow和其他博客文章中找到的多个问题上尝试的所有这些方法:
import { BrowserModule, HammerModule, HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import * as Hammer from 'hammerjs';
class MyHammerConfig extends HammerGestureConfig {
// Test #1
overrides = <any>{
swipe: { direction: hammer.DIRECTION_HORIZONTAL },
pinch: { enable: false },
rotate: { enable: false }
};
// Test #2
overrides = <any>{
swipe: { direction: Hammer.DIRECTION_ALL }
};
// Test #3
options = {
domEvents: true
}
// Test #4
buildHammer(element: HTMLElement) {
const mc = new Hammer(element, {
touchAction: 'pan-y'
});
return mc;
}
// Test #5
buildHammer(element: HTMLElement) {
const mc = new Hammer(element, {
touchAction: 'auto'
});
return mc;
}
}
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
HammerModule
],
providers: [
{
provide: Window,
useValue: window
},
{
provide: HAMMER_GESTURE_CONFIG,
useClass: MyHammerConfig
}
],
bootstrap: [
AppComponent
]
})
export class AppModule { }
所有这些方法都没有效果,因为它们的结果不同,并且在不同设备(例如iPhone和iPad)上不一致:
- ✗ 捏合缩放无法使用
- ✗ 垂直滚动无法使用
- ✗ 无法检测到对角线移动
当前解决方案
... 直接在组件中创建Hammer
:
import { Component, OnInit, ViewChild, ElementRef, OnDestroy, ViewChildren, QueryList } from '@angular/core';
import * as Hammer from 'hammerjs';
@Component({
selector: 'app-hero',
templateUrl: './hero.component.html',
styleUrls: ['./hero.component.scss']
})
export class HeroComponent implements OnInit, OnDestroy {
@ViewChild('list', { static: true }) list: ElementRef;
private hammertime: Hammer;
private isLocked: boolean = false;
ngOnInit() {
this.initHammer();
}
ngOnDestroy() {
// todo destroy hammertime
}
initHammer(): void {
this.hammertime = new Hammer(this.list.nativeElement, {touchAction : 'auto'});
this.hammertime.get('pan').set({ direction: Hammer.DIRECTION_HORIZONTAL, threshold: 60 });
this.hammertime.on('panleft panright', event => {
if (this.isLocked || event.maxPointers !== 1) {
return
};
this.goto(event.type === 'panLeft' ? 'next' : 'prev');
this.isLocked = true;
setTimeout(() => this.isLocked = false, 1000)
});
}
}
这个功能有以下优点:
- ✓ 可以缩放
- ✓ 可以上下滚动
- ✓ 可以检测到水平滑动
但以下问题存在或者不够好:
- ✗ 没有使用 HammerModule,不符合 Angular 的规范
- ✗ 无法检测对角线滑动
- ✗
Hammer
实例this.hammertime
和绑定的事件没有被正确销毁 - ✗ 为了避免
pan
事件多次触发使用了超时器 - ✗ 必须手动检测指针数量
问题?
- 如何使用 "Angular 规范" 来实现这个功能?
- 如何检测对角线滑动?
- 如果不能按照 "Angular 规范" 实现,如何正确销毁
this.hammertime
?