简体   繁体   English

HammerJS使用Mat-Tab滑动可阻止垂直滚动

[英]HammerJS swipe with Mat-Tabs blocking vertical scroll

SO I have a component in my Angular application that has tabs for categories of data with an array of values for the content of the tab. 因此,我在Angular应用程序中有一个组件,该组件具有用于数据类别的选项卡,以及用于选项卡内容的值数组。 I want to use HammerJS to swipe between the tabs for a more native experience. 我想使用HammerJS在选项卡之间滑动以获得更原生的体验。 I have installed this virtual scroll package also: https://github.com/rintoj/angular2-virtual-scroll to handle the amount of items I am preparing for the lists under each mat-tab . 我还安装了这个虚拟滚动包: https : //github.com/rintoj/angular2-virtual-scroll以处理我为每个mat-tab下的列表准备的项目数量。 I'll start by showing the data and the markup here: 我将从此处显示数据和标记开始:

Here is building the dummyData just to show how it is structured: 这是在构建dummyData只是为了展示其结构:

  dummyData: any[] = [];
  selectedTab: number;

  constructor() {
    this.selectedTab = 0;
    for (let i = 0; i < 3; i++) {
      const x = {
        key: i,
        value: []
      }
      for (let j = 0; j < 100; j++) {
        x.value.push(j);
      }
      this.dummyData.push(x);
    }
    console.log(this.dummyData);
  }

and here is the markup that loops this data to show the tabs and the lists: 这是循环此数据以显示选项卡和列表的标记:

  <mat-tab-group dynamicHeight="true" mat-stretch-tabs [selectedIndex]="selectedTab">
    <mat-tab *ngFor="let cat of dummyData" [label]="cat.key">
      <ng-template matTabContent>
        <virtual-scroll [items]="cat.value" (update)="viewPortItems = $event" (swipeleft)="swipe($event)" (swiperight)="swipe($event)" (swipeup)="swipe($event)" (swipedown)="swipe($event)">
          <p *ngFor="let item of viewPortItems; let i = index;">{{ item }}</p>
        </virtual-scroll>
      </ng-template>
    </mat-tab>
  </mat-tab-group>

Here is the swipe($event) method that is triggered for the (swipedirection) outputs on the virtual-scroll component: 这是为virtual-scroll组件上的(swipedirection)输出触发的swipe($event)方法:

  swipe(event) {
    console.log(event);
    if (this.selectedTab === 0 && event.type === 'swiperight') { return; }
    if ((this.selectedTab + 1) === this.dummyData.length && event.type === 'swipeleft') { return; }
    switch (event.type) {
      case 'swipeleft':
        this.selectedTab += 1;
        break;
      case 'swiperight':
        this.selectedTab -= 1;
        break;
    }
  }

For clarity here is my Hammer Configuration class and imports: 为了清楚起见,这里是我的Hammer Configuration类和导入:

import * as Hammer from 'hammerjs';
import { HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';

export class HammerConfig extends HammerGestureConfig {
  overrrides = <any>{
    'swipe': { velocity: 0.4, threshold: 20, direction: Hammer.DIRECTION_ALL },
    'pinch': { enable: false },
    'rotate': { enable: false }
  }
}

Which is also provided: { provide: HAMMER_GESTURE_CONFIG, useClass: HammerConfig } 还提供了以下内容: { provide: HAMMER_GESTURE_CONFIG, useClass: HammerConfig }

The purpose of this is for the user to be able to swipe the screen and move between tabs, like a user would on an Android or iOS application. 这样做的目的是使用户能够像在Android或iOS应用程序上一样滑动屏幕并在选项卡之间移动。 This setup works correctly and does in fact swipe between the tabs and loads the new data next and also virtual scrolls the data to make sure that only a set amount of items load at first. 此设置可以正常工作,并且实际上可以在选项卡之间滑动,然后加载新数据,并且还可以虚拟滚动数据以确保首先仅加载一定数量的项目。

My problem is that this now blocks all vertical scrolling from a mobile device as Hammer sets touch-action: none on the virtual-scroll component. 我的问题是,由于Hammer设置了touch-action: none ,这现在阻止了移动设备上的所有垂直滚动touch-action: none virtual-scroll组件上没有。 So I can still scroll with a mouse, but any vertical touch events do not do anything. 因此,我仍然可以使用鼠标滚动,但是任何垂直触摸事件都不起任何作用。 One thing I also noticed is that the (swipeup) and (swipedown) do not trigger any event in my component code. 我还注意到的一件事是(swipeup)(swipedown)不会在我的组件代码中触发任何事件。 I have also remvoed the swipeup and swipedown outputs just to make sure they aren't hindering the scroll, but still nothing when vertically dragging up or down on the screen. 我还删除了swipeup和swipedown输出,以确保它们不会妨碍滚动,但是在屏幕上垂直向上或向下拖动时仍然没有阻碍。

I also can confirm this doesn't have an issue with using the virtual-scroll package as I have tried it with a normal div that is not trying to lazy load the items, but just loads them all at once. 我还可以确认使用virtual-scroll软件包没有问题,因为我已经尝试过使用普通div进行尝试,而该div并不是试图延迟加载项目,而是一次加载所有项目。 Still get the same issue blocking any vertical scroll direction. 仍然会遇到相同的问题,阻止任何垂直滚动方向。 Since I will be using the virtual-scroll as that is more important that the gestures for tabs, I want to show my example here with that in the markup. 由于我将使用virtual-scroll因为virtual-scroll比制表符的手势更重要,因此我想在这里展示我的示例以及标记中的示例。

Anyone find a way to keep the native virtual scroll while enabling the horzontal swipe gestures? 任何人都可以找到一种方法来在启用水平滑动手势时保留本地虚拟滚动吗?

I appreciate any and all help here, thanks in advance! 感谢您在此提供的所有帮助,在此先感谢您!

I figured out a way to make this work while retaining vertical touch actions. 我想出了一种在保持垂直触摸动作的同时进行此工作的方法。 The hammer config I am using now looks like this: 我现在使用的Hammer配置看起来像这样:

export class HammerConfig extends HammerGestureConfig {
  overrrides = <any>{
    'swipe': { velocity: 0.4, threshold: 20, direction: Hammer.DIRECTION_ALL },
    'pinch': { enable: false },
    'rotate': { enable: false },
    'pan': { velocity: 0.4, threshold: 20, enable: true, direction: Hammer.DIRECTION_ALL }
  }
}

With the pan set for enabled. pan设置为启用。

Then I am using the (panend) output on my markup: (panend)="swipe($event)" , instead of the (swipedirection) output and this is my editted swipe method: 然后,我在标记上使用(panend)输出: (panend)="swipe($event)" ,而不是(swipedirection)输出,这是我编辑过的滑动方法:

  swipe(event) {
    console.log(event);
    event.preventDefault();
    if (this.selectedTab === 0 && event.additionalEvent === 'panright') { return; }
    if ((this.selectedTab + 1) === this.menu$.length && event.additionalEvent === 'panleft') { return; }
    switch (event.additionalEvent) {
      case 'panleft':
        this.selectedTab += 1;
        break;
      case 'panright':
        this.selectedTab -= 1;
        break;
    }
  }

From here this still blocks any vertical scrolling, but the one thing that will reenable the vertical scrolling is setting the touch-action: pan-y style on my virtual-scroll element: 从这里开始,它仍然会阻止任何垂直滚动,但是要重新启用垂直滚动的一件事是在我的virtual-scroll元素上设置touch-action: pan-y样式:

virtual-scroll {
    height: calc(100vh - 106px);
    padding: 0px 0px;
    will-change: transform;
    touch-action: pan-y !important;
}

From my understanding, this is telling the system to allow the native touch-action when scrolling in ay direction, but the x direction will then fire off the panend event and I can manage my tab index from there. 根据我的理解,这告诉系统在y方向滚动时允许本机触摸操作,但是x方向将触发panend事件,并且我可以从那里管理我的标签索引。 I hope this can be of help to anyone else trying to use side-to-side gestures while retaining the vertical scrolling behavior. 我希望这对尝试使用左右手势同时保持垂直滚动行为的其他人有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM