在 Angular 2 中实现滑动导航的最佳方式是啥?

Posted

技术标签:

【中文标题】在 Angular 2 中实现滑动导航的最佳方式是啥?【英文标题】:What is the best way to implement swipe navigation in Angular 2?在 Angular 2 中实现滑动导航的最佳方式是什么? 【发布时间】:2017-07-24 08:20:03 【问题描述】:

我是 Angular 2 的新手,正在寻找一种方法来为移动用户实现良好的标签触摸滑动导航,并通过滑动过渡到下一个标签视图。

到目前为止,我发现了一个名为 angular2-useful-swiper 的包,虽然我并不热衷于使用它,因为我最终会提前初始化我的组件,即使它们不在视图中。

有人知道为 Angular 2 实现基于标签滑动的导航的好方法吗?任何反馈将不胜感激。 :)

【问题讨论】:

【参考方案1】:

对于滑动检测,这里是比添加 HammerJS 更简单的解决方案:

在 app.component.html 中:

<div (touchstart)="swipe($event, 'start')" (touchend)="swipe($event, 'end')">
  App content here
</div>

在 app.component.ts 中:

private swipeCoord?: [number, number];
private swipeTime?: number;

swipe(e: TouchEvent, when: string): void 
  const coord: [number, number] = [e.changedTouches[0].clientX, e.changedTouches[0].clientY];
  const time = new Date().getTime();

  if (when === 'start') 
    this.swipeCoord = coord;
    this.swipeTime = time;
   else if (when === 'end') 
    const direction = [coord[0] - this.swipeCoord[0], coord[1] - this.swipeCoord[1]];
    const duration = time - this.swipeTime;

    if (duration < 1000 //
      && Math.abs(direction[0]) > 30 // Long enough
      && Math.abs(direction[0]) > Math.abs(direction[1] * 3))  // Horizontal enough
        const swipe = direction[0] < 0 ? 'next' : 'previous';
        // Do whatever you want with swipe
    
  

注意:我尝试了 HammerJS 解决方案,但无法将其配置为忽略鼠标手势,因为您无法直接访问 Hammer 对象。所以选择一些文本会强制导航到下一页...

【讨论】:

我在hammer.js github上的一个bug问题中发布了你的解决方案,希望他们能在我们使用它的问题上做出反应...... 这是一个非常轻量级且很棒的解决方案,只有一个小漏洞是,如果您在一个旁边双击(如弹奏键盘),它会将其检测为滑动。 这个小指令怎么样github.com/aGoncharuks/angular-swipe-directive【参考方案2】:

你可以使用HammerJS来实现触摸动作,你可以按照这个plunker为例。

包含hammer.js文件

<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.js"></script>

npm install hammerjs --save

对于hammerjs 的浏览器触摸支持,包括

 <script src="http://cdn.rawgit.com/hammerjs/touchemulator/master/touch-emulator.js"></script>
<script>

在 app.module.ts 中导入

import  HammerGestureConfig, HAMMER_GESTURE_CONFIG  from '@angular/platform-browser';

export class MyHammerConfig extends HammerGestureConfig  
  overrides = <any>
    'swipe': velocity: 0.4, threshold: 20 // override default settings
  


@NgModule(
  imports: [BrowserModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [ 
    provide: HAMMER_GESTURE_CONFIG, 
    useClass: MyHammerConfig 
  ] // use our custom hammerjs config
)

plunker link for example

要实现标签angular2-material 是一个不错的起点,请关注this link

【讨论】:

【参考方案3】:

首先安装hammerjs和action touch-action polyfill:

$ npm install hammerjs hammer-timejs

然后将导入添加到“app.module.ts”,以便使用/捆绑它们:

import 'hammerjs';
import 'hammer-timejs';

现在您可以处理动作的事件: 旋转 捏 新闻 潘 点击 滑动

例如你可以说:

&lt;li *ngFor="let employee of employeesList;" (swiperight)="myswiperight(employee)" (swipeleft)="myswipeleft(employee)"&gt;

或者:

&lt;div (panstart)="onPanStart($event)" (panmove)="onPan($event)"&gt;

参考:https://saschwarz.github.io/angular2-gestures-slides/#/

【讨论】:

【参考方案4】:

我根据@Elvis Metodiev 的回答和@pikiou 创建了一个指令:

swipe.directive.ts

import  Directive, EventEmitter, HostListener, Output  from '@angular/core';

@Directive( selector: '[swipe]' )
export class SwipeDirective 

    @Output() next = new EventEmitter<void>();
    @Output() previous = new EventEmitter<void>();

    swipeCoord = [0, 0];
    swipeTime = new Date().getTime();

    constructor()  

    @HostListener('touchstart', ['$event']) onSwipeStart($event) 
        this.onSwipe($event, 'start');
    

    @HostListener('touchend', ['$event']) onSwipeEnd($event) 
        this.onSwipe($event, 'end');
    

    onSwipe(e: TouchEvent, when: string) 
        this.swipe(e, when);
    

    swipe(e: TouchEvent, when: string): void 

        const coord: [number, number] = [e.changedTouches[0].clientX, e.changedTouches[0].clientY];
        const time = new Date().getTime();

        if (when === 'start') 
            this.swipeCoord = coord;
            this.swipeTime = time;
         else if (when === 'end') 
            const direction = [coord[0] - this.swipeCoord[0], coord[1] - this.swipeCoord[1]];
            const duration = time - this.swipeTime;

            if (duration < 1000 //
                && Math.abs(direction[0]) > 30 // Long enough
                && Math.abs(direction[0]) > Math.abs(direction[1] * 3))  // Horizontal enough
                const swipeDir = direction[0] < 0 ? 'next' : 'previous';
                if (swipeDir === 'next') 
                    this.next.emit();
                 else 
                    this.previous.emit();
                
            
        
    

tour.component.component.ts

<div
  ...
  swipe
  (next)="onRotateNext()"
  (previous)="onRotatePrevious()"
>
...
</div>

【讨论】:

【参考方案5】:

我设法想出了一个一次写入,随处使用的函数类型,我将它放在一个名为“gestures”的目录中,然后创建一个名为“swipe.ts”的文件并将其放入其中。

let swipeCoord = [0, 0];
let swipeTime = new Date().getTime();

export function swipe(e: TouchEvent, when: string): void 

    const coord: [number, number] = [e.changedTouches[0].clientX, e.changedTouches[0].clientY];
    const time = new Date().getTime();

    if (when === 'start') 
        swipeCoord = coord;
        swipeTime = time;
     else if (when === 'end') 
        const direction = [coord[0] - swipeCoord[0], coord[1] - swipeCoord[1]];
        const duration = time - swipeTime;

        if (duration < 1000 //
            && Math.abs(direction[0]) > 30 // Long enough
            && Math.abs(direction[0]) > Math.abs(direction[1] * 3))  // Horizontal enough
            const swipeDir = direction[0] < 0 ? 'next' : 'previous';
            if (swipeDir === 'next') 
                alert('swipe next');
             else 
                alert('swipe prev');
            
        
    

然后导入所需的组件,如下所示:

import swipe from '../../gestures/swipe';

并创建一个名为:

onSwipe(e: TouchEvent, when: string) 
        swipe(e, when);
    

在所需组件的 html 中,使用以下代码:

    <div (touchstart)="onSwipe($event, 'start')"
         (touchend)="onSwipe($event, 'end')">

       <!-- whatever content you have goes here -->

    </div>

PS - 归功于@pikiou。我刚刚提出了更高级别的抽象,这对我来说更有意义。

【讨论】:

以上是关于在 Angular 2 中实现滑动导航的最佳方式是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 3.0 中实现滑动以在没有导航栏的情况下向后导航

在 ASP.NET MVC 2 中实现 DropDownList 的最佳方式?

在 ViewPager 中实现弹性/反弹动画效果的最佳方法是啥?

滑动 ViewController 时出现导航栏错误

在 Rails 中实现“查找商店”功能的最佳方式是啥?

如何在 SPA 中实现 OAuth 隐式流?