Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure Hammerjs events with angular2

How can I configure hammerjs events in angular2?

To use hammerjs events with angular2 I just have to include events on my html like this:

<div (press)="onLongPress($event)"></div>

In this case (press) will have time of 251 milliseconds, by default. Hammerjs press event documentation

How do I configure this time to have different value?

like image 806
afvieira Avatar asked Mar 07 '16 11:03

afvieira


3 Answers

With Angular 2.0.1, there's actually a direct way to configure hammerjs:

// app.module.ts

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

export class MyHammerConfig extends HammerGestureConfig  {
  overrides = <any>{
      // override hammerjs default configuration
      'pan': {threshold: 5},
      'swipe': {
           velocity: 0.4,
           threshold: 20,
           direction: 31 // /!\ ugly hack to allow swipe in all direction
      }
  }
}

@NgModule({
  imports:      [ ...],
  declarations: [ ... ],
  bootstrap:    [ ... ],
  providers:    [ { 
                    provide: HAMMER_GESTURE_CONFIG, 
                    useClass: MyHammerConfig 
                } ]
})

Note that I'm using a hack to allow swipe in all direction by using the current value of Hammer.DIRECTION_ALL. Though that value might not change for a while, I'll update this post as soon as someone whispers a way to access Hammer.DIRECTION_ALL value directly from the app module.

like image 60
Bob Avatar answered Nov 04 '22 13:11

Bob


It's not something easy since it's internally handled by the CustomHammerGesturesPlugin class. I see two approaches:

  • Provide your own Hammer plugin and register it. When the Hammer object is instantiated, you need to provide your configuration as second parameter:

    @Injectable()
    export class CustomHammerGesturesPlugin extends HammerGesturesPlugin {
      addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
        var zone = this.manager.getZone();
        eventName = eventName.toLowerCase();
    
        return zone.runOutsideAngular(function() {
          // Creating the manager bind events, must be done outside of angular
          var mc = new Hammer(element); // <-------
          mc.get('pinch').set({enable: true});
          mc.get('rotate').set({enable: true});
          var handler = function(eventObj) { zone.run(function() { handler(eventObj); }); };
          mc.on(eventName, handler);
          return () => { mc.off(eventName, handler); };
        });
      }
    }
    

    Since the HammerGesturesPlugin provider is automatically register when using the bootstrap function, you need to use this code to bootstrap your application (see https://github.com/angular/angular/blob/master/modules/angular2/platform/browser.ts#L110 and https://github.com/angular/angular/blob/master/modules/angular2/src/platform/browser_common.ts#L79):

    platform(BROWSER_PROVIDERS).application(appProviders).bootstrap(appComponentType);
    
  • A workaround could be to intercept the instantiation of the Hammer object (see Can I intercept a function called directly?):

    <script>
      window.TargetHammer = window.Hammer;
      window.Hammer = function() {
        var mc = new TargetHammer(arguments[0]);
        mc.get('press').set({
          time: 1000
        });
        return mc;
      }
    </script>
    

    See this plunkr: https://plnkr.co/edit/eBBC9d?p=preview.

Otherwise I don't know which version of Angular2 you use but there is a problem with Hammer events (beta.0 seems to be okay):

  • https://github.com/angular/angular/issues/6993
like image 25
Thierry Templier Avatar answered Nov 04 '22 11:11

Thierry Templier


In order to configure Hammer.js events you can use recognizer (options for the event). This can be used in a directive as shown here:

import {Directive, ElementRef, Input, OnInit, OnDestroy} from '@angular/core';
import {Gesture} from 'ionic-angular/gestures/gesture';
declare var Hammer: any

@Directive({
  selector: '[spLongPress]'
})
export class LongPressDirective implements OnInit, OnDestroy {
  el: HTMLElement;
  pressGesture: Gesture;

  constructor(el: ElementRef) {
    this.el = el.nativeElement;
  }

  ngOnInit() {
    this.pressGesture = new Gesture(this.el, {
      recognizers: [
        [Hammer.Press, { time: 500 }]
      ]
    });
    this.pressGesture.listen();
    this.pressGesture.on('press', e => {
      console.log('pressed!!');
    })
  }

  ngOnDestroy() {
    this.pressGesture.destroy();
  }
}

This fires the event after 500ms.

like image 44
Norbert Lanzanasto Avatar answered Nov 04 '22 13:11

Norbert Lanzanasto