【问题标题】:Capture swipe event on entire screen with Hammer and Angular 8使用 Hammer 和 Angular 8 在整个屏幕上捕获滑动事件
【发布时间】:2020-01-19 16:37:44
【问题描述】:

我正在尝试在我的应用程序的整个屏幕上捕捉滑动手势。这个想法是让其他服务可以侦听这些调度操作,在本例中是用于导航目的的路由器。

因为我只希望将这些侦听器放在一个地方,所以我尝试将它们附加到 body 或覆盖我的应用程序屏幕的 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 和我拥有但不在我的路由器插座上的状态栏,也不是底部包含一些按钮的工具栏。

那么,我如何在整个应用程序上捕获滑动?

我尝试创建一个 sn-p 来重现该问题,但没有 Angular 组件,它的行为几乎与我希望我的应用程序一样。尽管尝试从 sn-p 中的按钮边距周围滑动时,可以观察到与我的问题类似的行为。

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>

【问题讨论】:

    标签: angular angular-material2 ngrx gesture hammer.js


    【解决方案1】:

    当您想将 Hammer 添加到 Angular 8 应用程序时,您需要作为提供者 HAMMER_GESTURE_CONFIG 并使用类 HammerGestureConfig

      providers: [
        {
          provide: HAMMER_GESTURE_CONFIG,
          useClass: HammerGestureConfig
        }
      ]
    

    好吧,如果您想使用另一个类,请覆盖某些属性-例如你想向所有方向滑动-,你创建一个扩展 HammerGestureConfig 的类并在提供程序中使用这个类

    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 来备注必要的取消订阅

    【讨论】:

    • 更改为 document.documentElement 完成了这项工作!您愿意解释一下 rxjs 运算符的用途吗?在 OnInit 中只有这两行似乎可以正常工作:const mc = new Hammer(document.documentElement); mc.on('swipeleft...。如果不指定提供者,它似乎也可以正常工作。
    • 前段时间我得到了使用 fromEvent 的狂热,实际上我使用锤子的经验非常短,所以你的方法可能比我的更正确
    猜你喜欢
    • 2017-03-15
    • 2012-04-19
    • 2015-11-21
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多