web-dev-qa-db-fra.com

Utilisation d'événements mobiles dans Angular2

Je me demandais si je pouvais obtenir de l'aide en ce qui concerne les événements pour appareils mobiles. Je cherchais un moyen de lier les fonctions aux événements de glissement dans Angular 2. J'ai vu dans ce ce problème sur Github qui mentionne qu'Angular 2 utilise Hammer.js pour la gestion d'événements mobiles.

J'ai du mal à faire en sorte que l'événement fonctionne car j'obtiens l'erreur suivante: 

EXCEPTION: Hammer.js n'est pas chargé, impossible de lier l'événement swipeleft

Un extrait de mon code est ci-dessous:

import {Component, View, AfterContentInit} from 'angular2/core';
import {HelperService} from "./helper-service";
import {HammerGesturesPluginCommon} from 'angular2/src/platform/dom/events/hammer_common'

@View({
  template: `<div [id]="middleCircle" (swipeleft)="doThis()"></div>`
})

export class ColumnDirective implements AfterContentInit {
  constructor(private helperService:HelperService) {}
  doThis(){
     console.log('This thing has been done.');
   }
 }

Si j'ajoute Hammer Gestures à mon constructeur, j'obtiens cette erreur:

constructor(private helperService:HelperService, private hammerGesturesPluginCommon: HammerGesturesPluginCommon) {}

EXCEPTION: Aucun fournisseur pour t! (ColumnDirective -> t)

Toute aide concernant ce problème serait appréciée!

11
Eric Gonzalo

Après beaucoup de bidouilles, je n'ai pas réussi à faire fonctionner HammerGesturesPluginCommon d'Angular2 (jusqu'à présent). Inspiré par la réponse de Bill Mayes, je vous soumets la présente comme une élaboration de sa réponse à laquelle je suis parvenu à travailler (testé sur un iPad mini et un téléphone Android). 

Fondamentalement, ma solution est la suivante.

Commencez par référencer manuellement hammer.js dans les balises de script de votre fichier index.html (je fais également référence à hammer-time pour éliminer le délai de 300 ms):

Deuxièmement, installez les définitions de type pour hammerjs (tsd install hammerjs -save). Ensuite, vous pouvez créer une directive d'attribut Angular2 comme ceci: 

/// <reference path="./../../../typings/hammerjs/hammerjs.d.ts" />
import {Directive, ElementRef, AfterViewInit, Output, EventEmitter} from 'angular2/core';
@Directive({
    selector: '[hammer-gestures]'
})
export class HammerGesturesDirective implements AfterViewInit {
    @Output() onGesture = new EventEmitter();
    static hammerInitialized = false;
    constructor(private el: ElementRef) {

    }
    ngAfterViewInit() {

        if (!HammerGesturesDirective.hammerInitialized) {

            let hammertime = new Hammer(this.el.nativeElement);
            hammertime.get('swipe').set({ direction: Hammer.DIRECTION_ALL });
            hammertime.on("swipeup", (ev) => {
                this.onGesture.emit("swipeup");
            });
            hammertime.on("swipedown", (ev) => {
                this.onGesture.emit("swipedown");
            });
            hammertime.on("swipeleft", (ev) => {
                this.onGesture.emit("swipeleft");
            });
            hammertime.on("swiperight", (ev) => {
                this.onGesture.emit("swiperight");
            });
            hammertime.on("tap", (ev) => {
                this.onGesture.emit("tap");
            });

            HammerGesturesDirective.hammerInitialized = true;
        }


    }
}

Vous devez définir Hammer.DIRECTION_ALL si vous souhaitez détecter les balayages verticaux (haut/bas) (les balayages gauche/droit sont définis par défaut et non verticaux). Plus d'options peuvent être trouvées sur l'api de marteau ici: http://hammerjs.github.io/api/#hammer

Enfin, dans votre composant parent, vous pouvez faire quelque chose comme ceci: 

import {Component} from "angular2/core";
import {HammerGesturesDirective} from "./path/HammerGesturesDirective";

    @Component({
        selector: "my-ng2-component",
        template: `<div style='width:100px; height: 100px;background-color: red' 
            (onGesture)="doSwipe($event)" hammer-gestures></div>`,
        directives: [HammerGesturesDirective]

    })
    export class MyNg2Component {
        constructor() { }

        doSwipe(direction: string) {
            alert(direction);
        }

    }

De cette façon, il vous suffit de référencer l'attribut hammer-gestures lorsque vous souhaitez activer les gestes de frappe sur un élément particulier. Remarque: l'élément semble avoir besoin d'un identifiant unique pour fonctionner

13
brando

Et bien, longtemps après l’opération, mais si vous n’avez que des exigences simples et que vous ne voulez pas vous défoncer avec hammer.js, voici un swiper horizontal de base. Placez-vous simplement dans un composant et ajoutez vos propres fonctions doSwipeLeft et doSwipeRight.

  touch1 = {x:0,y:0,time:0};

  @HostListener('touchstart', ['$event'])
  @HostListener('touchend', ['$event'])
  //@HostListener('touchmove', ['$event'])
  @HostListener('touchcancel', ['$event'])
  handleTouch(ev){
    var touch = ev.touches[0] || ev.changedTouches[0];
    if (ev.type === 'touchstart'){
      this.touch1.x = touch.pageX;
      this.touch1.y = touch.pageY;
      this.touch1.time = ev.timeStamp;
    } else if (ev.type === 'touchend'){
      var dx = touch.pageX - this.touch1.x;
      var dy = touch.pageY - this.touch1.y;
      var dt = ev.timeStamp - this.touch1.time;

      if (dt < 500){
        // swipe lasted less than 500 ms
        if (Math.abs(dx) > 60){
          // delta x is at least 60 pixels
          if (dx > 0){
            this.doSwipeLeft(ev);
          } else {
            this.doSwipeRight(ev);
          }
        }
      }
    } 
  }
7
Mike M

J'étais un peu hésitant à ajouter des gestes de balayage à ma candidature car les réponses fournies semblaient suggérer que ce serait un peu compliqué.

EXCEPTION: Hammer.js n'est pas chargé, impossible de lier l'événement swipeleft

Cette erreur est facilement traitée en chargeant simplement hammer.js. Aucun code personnalisé nécessaire.

L’autre erreur mentionnée dans les commentaires semble avoir été un bogue corrigé à partir de rc1.

3
Kevin Stricker

J'ai réussi à obtenir quelque chose qui fonctionne en contournant l'intégration intégrée de Hammer et en exécutant la mienne:

import { Component, ElementRef, AfterViewInit } from 'angular2/core';

@Component({
  selector: 'redeem',
  templateUrl: './redeem/components/redeem.html'
})
export class RedeemCmp implements AfterViewInit {

    static hammerInitialized = false;

    constructor(private el:ElementRef) { }

    ngAfterViewInit() {
        console.log('in ngAfterViewInit');
        if (!RedeemCmp.hammerInitialized) {
            console.log('hammer not initialised');

            var myElement = document.getElementById('redeemwrap');
            var hammertime = new Hammer(myElement);
            hammertime.on('swiperight', function(ev) {
                console.log('caught swipe right');
                console.log(ev);
            });

            RedeemCmp.hammerInitialized = true;
        } else {            
            console.log('hammer already initialised');
        }
    }
}
2
Billy Mayes

"EXCEPTION: Hammer.js n'est pas chargé, impossible de lier l'événement swipeleft" est déclenché car hammerjs doit être inclus dans la page.

Exemple: <script src = "node_modules/hammerjs/hammer.js"> </ script>

J'ai lu toutes les autres réponses sur l'utilisation des hammerjs avec angular et elles ont l'air hacky… .. Par défaut, HammerJs a désactivé les méthodes SwipeDown et SwipeUp. Toutes les réponses précédentes ne sont pas correctes angular2 TypeScript pour résoudre le problème des gestes ou annuler les réglages par défaut de marteau .

Vous voilà:

La première chose dont nous aurons besoin est une typographie hammerjs pour angular2.

typings install github:DefinitelyTyped/DefinitelyTyped/hammerjs/hammerjs.d.ts#de8e80dfe5360fef44d00c41257d5ef37add000a --global --save

Nous devons ensuite créer notre classe de configuration de remplacement personnalisée . Cette classe peut être utilisée pour remplacer tous les paramètres de configuration hammerjs et angular2 hammerjs par défaut.

hammer.config.ts:

import { HammerGestureConfig } from '@angular/platform-browser';
import {HammerInstance} from "@angular/platform-browser/src/dom/events/hammer_gestures";


export class HammerConfig extends HammerGestureConfig  {

    buildHammer(element: HTMLElement): HammerInstance {
        var mc = new Hammer(element);

        mc.get('pinch').set({ enable: true });
        mc.get('rotate').set({ enable: true });

        mc.add( new Hammer.Swipe({ direction: Hammer.DIRECTION_ALL, threshold: 0 }) );

        for (let eventName in this.overrides) {
            mc.get(eventName).set(this.overrides[eventName]);
        }

        return mc;
    }
}

La dernière chose à faire est d’ouvrir notre fichier boostrap principal et d’insérer notre configuration personnalisée dans la méthode boostrap comme ceci:

// ... other imports ...
import { HammerConfig } from './shared/hammer.config';

bootstrap(AppComponent, [
    provide(HAMMER_GESTURE_CONFIG, { useClass: HammerConfig })
]);

Maintenant, dans notre application, nous pouvons utiliser swipeDown et swipeUp

<div class="some-block" (swipeDown)="onSwipeDown"></div>

Cette demande d'extraction permettait de remplacer les paramètres par défaut et me donnait le point de départ pour trouver le bon chemin

https://github.com/angular/angular/pull/7924

1
user991

Vous devez ajouter

HelperService et HammerGesturesPluginCommon aux fournisseurs quelque part, soit dans l'annotation @Component(...), soit dans bootstrap(AppComponent, [...]) pour supprimer l'erreur "Aucun fournisseur pour ..."

Avez-vous ajouté une balise de script pour Hammer.js quelque part sur votre page d'entrée?

0