简体   繁体   中英

HammerJs: enable vertical scroll with horizontal swipe

I've got an angular 7 website, and I want to add horizontal swipe to one component, and vertical swipe to another (the components are in the same module). I'm using hammerjs for that.

By default, hammerjs disables vertical swipe, so I enabled swipping in all directions with the code below.

export class MyHammerConfig extends HammerGestureConfig
{
  overrides = <any>{
    swipe: {direction: Hammer.DIRECTION_ALL},
  };
}

//declare provider in AppModule
providers: [
    {
      provide: HAMMER_GESTURE_CONFIG,
      useClass: MyHammerConfig
    }
]

The problem is vertical scrolling does not work on the component with the horizontal swipe. From what I've read, the solution is to add touch-action: pan-y in the component with the horizontal swipe.

However, this works on chrome but safari does not recognise the touch-action property.

My idea was to declare multiple providers for HAMMER_GESTURE_CONFIG , at the component level:

  • on the component with horizontal swipe, use a provider which only allows horizontal swipe
  • on the other one, only enable vertical swipe

However, component-level providers do not seem to take my providers into account.

Here is some code I tried to use to only enable horizontal swipe

export class HorizontalHammerConfig extends HammerGestureConfig
{
  overrides = <any>{
    swipe: {Hammer.DIRECTION_HORIZONTAL},
    pinch: {enable: false},
    rotate: {enable: false}
  };
}

//Component declaration
@Component({
  ...

  providers:[
    {
      provide: HAMMER_GESTURE_CONFIG,
      useClass: HorizontalHammerConfig
    }],

Any idea?

Edit : Here is a stackblitz example demostrating the issue. The component level providers are ignored.

I found the solution there .

Basically, the custom configuration has to override the buildHammer class, so different hammerjs options can be used depending on the context.

app.module.ts

export class MyHammerConfig extends HammerGestureConfig
{
  overrides = <any>{
    swipe: {direction: Hammer.DIRECTION_ALL},
  };

  buildHammer(element: HTMLElement)
  {
    let options = {};

    if (element.attributes['data-mc-options'])
    {
      try
      {
        options = JSON.parse(element.attributes['data-mc-options'].nodeValue);
      }
      catch (err)
      {
        console.error('An error occurred when attempting to parse Hammer.js options: ', err);
      }
    }

    const mc = new Hammer(element, options);


    // retain support for angular overrides object
    for (const eventName of Object.keys(this.overrides))
    {
      mc.get(eventName).set(this.overrides[eventName]);
    }

    return mc;
  }
}

And then, in the component template, pass the extra option as a json string.

component.html

<div (swipeleft)="onSwipeLeft()" data-mc-options='{ "touchAction": "pan-y" }'">
</div>

This works with safari/iOS

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM