2016-03-01 14 views
9

Ich fragte mich, ob ich etwas Hilfe in Bezug auf Ereignisse für mobile Geräte bekommen könnte. Ich suchte nach einer Möglichkeit, Funktionen zu binden, um Ereignisse in Angular 2 zu wischen. Ich sah in dieser this issue auf Github, die erwähnt, dass Angular 2 Hammer.js für mobile Ereignisbehandlung verwendet.Verwendung von mobilen Ereignissen in Angular2

ich einige Probleme mit der Veranstaltung bekommen zu arbeiten, weil ich die folgende Fehlermeldung erhalten:

EXCEPTION: Hammer.js is not loaded, can not bind swipeleft event

Ein Ausschnitt meiner Code ist unten:

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.'); 
    } 
} 

Wenn ich in Hammer Gestures hinzufügen zu meinen Konstruktor, bekomme ich diesen Fehler:

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

EXCEPTION: No provider for t! (ColumnDirective -> t)

Jede Hilfe mit diesem Problem wäre willkommen!

+0

Ich habe gerade diesen Thread gefunden, wie ich das gleiche Ding zu implementieren versuche. Ich werde dich wissen lassen, ob ich etwas finde. –

+0

Ich konnte über die "Hammer.js ist nicht geladen" durch Hinzufügen eines Skript-Tags für hammer.js zu meiner index.html (ich benutze die angular 2 Seed-Projekt), aber wenn ich einen Swipe auslösen, bekomme ich Jetzt erhalten Sie eine riesige Liste von Fehlern, die mit "EXCEPTION: RangeError: Maximale Call-Stack-Größe überschritten" beginnen. –

+0

Yeah @BillyMayes das gleiche Problem jetzt. –

Antwort

13

Nach viel Hantieren ich keinen Erfolg hatte Angular2 die HammerGesturesPluginCommon bekommen (bisher) zu arbeiten, . Inspiriert von Bill Mayes Antwort, reiche ich dies als eine Ausarbeitung seiner Antwort ein, die ich in der Lage war zu arbeiten (getestet auf einem Ipad Mini und einem Android Telefon).

Grundsätzlich ist meine Lösung wie folgt.

Zuerst manuell hammer.js in dem Script-Tags Ihrer index.html-Datei verweisen (I Referenz auch Hammer-Zeit, die 300 ms Verzögerung zu beseitigen):

Zweitens installieren Sie die Typdefinitionen für hammerjs (tsd install hammerjs -save). Dann können Sie eine Angular2 attibute Richtlinie wie folgt erstellen:

/// <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; 
     } 


    } 
} 

Sie Hammer.DIRECTION_ALL festlegen müssen, wenn Sie vertikal erkannt werden soll (oben/unten) klaut (links/rechts Seitenhiebe sind standardmäßig nicht vertikal).Weitere Optionen können über den Hammer api hier: http://hammerjs.github.io/api/#hammer

schließlich in Ihrer Mutter Komponente, die Sie so etwas tun kann:

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); 
     } 

    } 

Auf diese Weise brauchen Sie nur das Attribut Hammer-Gesten referenzieren wenn Sie Hammergesten für ein bestimmtes Element aktivieren möchten. Hinweis: Das Element scheint eine eindeutige ID zu benötigen, um zu arbeiten.

+2

Ich habe das noch nicht getestet, aber ich mag die Idee so sehr, dass ich "cool" laut im Büro gesagt habe. Es sieht sauber aus –

+0

gut erklärte Antwort :) +1 –

+0

Ich fand, dass das Hinzufügen dieser Direktive zu mehreren Elementen in meiner Komponente, aufgrund der statischen 'hammerInitialized' -Eigenschaft, nur das erste Element verdrahtet wurde. Ich entfernte den Scheck und es scheint für mich besser zu funktionieren. (laut "cool" auch.) – GaryB96

0

Sie müssen irgendwo

HelperService und HammerGesturesPluginCommon an den Anbieter hinzuzufügen, entweder in der @Component(...) Anmerkung oder in bootstrap(AppComponent, [...]) zu den Fehler loszuwerden „Kein Anbieter für ...“

Haben fügen Sie ein Skript Tag für Hammer.js irgendwo auf Ihrer Startseite?

+0

Ich habe eine 'providers: [HammerGesturesPluginCommon]' zu meiner '@ Component' hinzugefügt und Hammer.js in ein Skript-Tag von einem cdn eingefügt, jetzt bekomme ich die maximale Call-Stack-Größe überschritten, scheint uns näher zu sein! –

+0

Vielleicht https://github.com/angular/angular/issues/5964 oder https://github.com/angular/angular/issues/5964 bieten einige Informationen. Soweit ich mich erinnern kann, habe ich 'zone.js' nicht explizit hinzugefügt (ich bin selbst nicht auf dieses Problem gestoßen, erinnere mich einfach daran, die Diskussionen zu sehen und ich weiß nicht, ob das immer noch aktuell ist). Könnte auch ein Problem mit der Reihenfolge der Skript-Tags sein. –

2

konnte ich etwas zum Laufen bringen, indem die eingebaute in Hammer Integration umgeht und meine eigene Lauf:

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'); 
     } 
    } 
} 
+0

Das scheint eine viel bessere Idee zu sein. Da wir noch in der Beta sind, sind viele Dinge immer noch ziemlich fehlerhaft. Danke für die Hilfe! –

+0

@BillMayes vielen Dank. Ich habe deine Antwort unter – brando

+0

ausgearbeitet. Unter Verwendung von RC1 heißt es Hammer gibt mir Fehler in der Zeile 'var hammertime = new Hammer (myElement);' - Hammer nicht definiert. Irgendeine Idee, was sich in RC1 geändert hat? – LorDex

3

Ich zögerte etwas, meiner Anwendung Swipe-Gesten hinzuzufügen, weil die Antworten hier darauf hinwiesen, dass es etwas unordentlich wäre.

EXCEPTION: Hammer.js is not loaded, can not bind swipeleft event

Dieser Fehler wird mit durch einfaches Laden hammer.js leicht behandelt. Kein benutzerdefinierter Code erforderlich.

Der andere Fehler, der in den Kommentaren erwähnt wird, scheint ein Fehler gewesen zu sein, der ab rc1 behoben wird.

1

„AUSNAHME: Hammer.js nicht geladen wird, kann nicht swipeleft Ereignis binden“ ausgelöst, da hammerjs in Seite enthalten sein muss.

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

Ich habe alle anderen Antworten zu lesen, wie mit Winkel verwenden hammerjs und sie sehen Hacky. Standardmäßig hat HammerJs SwipeDown und SwipeUp Methoden deaktiviert. Alle vorherigen Antworten sind nicht richtig angular2 Typescript Weg, Gesten Problem zu lösen oder Standardeinstellungen von Hammer zu überschreiben. Ich brauchte ungefähr 4 Stunden, um in angular2 und hammerjs commits zu graben.

Sie sind hier:

Das erste, was wir hammerjs Typisierungen für sind angular2 benötigen.

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

Als nächstes müssen wir unsere benutzerdefinierte überschreibende Config-Klasse erstellen. Diese Klasse kann verwendet werden, um alle standardmäßigen Einstellungen für hammerjs und angular2 hammerjs zu überschreiben.

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; 
    } 
} 

Letzte, was wir tun müssen, ist unsere Bootstrap-Datei zu öffnen und unsere eigene Config in Bootstrap-Methode wie folgt ein:

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

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

Jetzt in unserer Anwendung können wir swipeDown und swipeUp verwenden

Diese Pull-Anforderung aktiviert übersch Iding von Standardeinstellung und gab Start mir Punkt richtigen Weg zu finden:

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

5

Nun, lange nach dem OP, aber wenn Sie haben nur einfache Anforderungen und wollen nicht mit hammer.js Dreck Hier ist ein einfacher horizontaler Swiper. Einfach in eine Komponente fallen lassen und eigene doSwipeLeft und doSwipeRight Funktionen hinzufügen.

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); 
      } 
     } 
     } 
    } 
    } 
Verwandte Themen