artuska
artuska

Reputation: 874

Configure hammer.js gestures for different modules in Angular

I have a standard Hammer gestures custom config in my root module:

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

export class CustomHammerConfig extends HammerGestureConfig {
    overrides = {
        pan: {
            direction: 6 // this code enables only horizontal direction
        },
        pinch: {
            enable: false
        },
        rotate: {
            enable: false
        }
    };
}

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        //
    ],
    providers: [
        //
        {
            provide: HAMMER_GESTURE_CONFIG,
            useClass: CustomHammerConfig
        }
    ],
    bootstrap: [
        AppComponent
    ]
})

I have a Carousel component which must be able to pan only horizontally, so the vertical pan on Carousel component block will not prevent the whole page scroll in mobile devices.

So, global Hammer gestures config works fine for my Carousel component.

But I have another component — a Gallery component — which pan gestures must be enabled in all directions. I try to configure the Hammer in my Gallery module:

import { CommonModule} from '@angular/common';
import { NgModule } from '@angular/core';

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

import { GalleryComponent } from './gallery.component';

class GalleryHammerConfig extends HammerGestureConfig {
    overrides = {
        pan: {
            direction: 31 // this code enables all directions
        }
    };
}

@NgModule({
    imports: [
        CommonModule
    ],
    declarations: [
        GalleryComponent
    ],
    providers: [
        {
            provide: HAMMER_GESTURE_CONFIG,
            useClass: GalleryHammerConfig
        }
    ],
    exports: [
        GalleryComponent
    ]
})

export class GalleryModule {}

But it does not take any effect — Angular understands only root module configured Hammer gestures.

If I remove Hammer gestures config from the root App module and apply it to the Carousel module, so the Carousel has its own custom config and the Gallery also has its own custom config — well, it does not do any effect at all — Angular takes its own default Hammer gestures config and uses it instead of my custom configs.

So, how do I apply different Hammer gestures configs for different components?

Upvotes: 5

Views: 3972

Answers (2)

Ryan Kara
Ryan Kara

Reputation: 437

You could use the @angular/platform-browser built in gestures instead of attempting to override them.

Your carousel component could use the panleft and panright methods, while your gallery app could use the pan method. Even if they're being used at the same time, you will not have a collision.

Here's a stackblitz I put together of the pan gesture, but you can add it on any element like so as long as you are importing hammerjs into your application.

<div (pan)="onpan($event)"></div>

Upvotes: 2

Riceball LEE
Riceball LEE

Reputation: 1591

That is impossible to use the same gesture directive to do so. But you can create a new gesture directive.

export interface Recognizer {
  new(options?: any): Recognizer;
  recognizeWith(otherRecognizer: Recognizer | string): Recognizer;
}

export interface RecognizerStatic {
  new(options?: any): Recognizer;
}

export class GestureConfig extends HammerGestureConfig {
  private _hammer = typeof window !== 'undefined' ? (window as any).Hammer : null;

  buildHammer(element: HTMLElement): any {
    const mc = new this._hammer(element, this._hammerOptions || undefined);
    const pan = new this._hammer.Pan();
    const panYourWay = this._createRecognizer(pan, {event: 'panYourWay', direction: 31});
    // Add customized gestures to Hammer manager
    mc.add([panYourWay]);
    return mc; 
  }

 /** Creates a new recognizer, without affecting the default recognizers of HammerJS */
  private _createRecognizer(base: Recognizer, options: any, ...inheritances: Recognizer[]) {
    let recognizer = new (base.constructor as RecognizerStatic)(options);

    inheritances.push(base);
    inheritances.forEach(item => recognizer.recognizeWith(item));

    return recognizer;
  }
}

Upvotes: 0

Related Questions