davidfig / pixi-viewport

A highly configurable viewport/2D camera designed to work with pixi.js
https://davidfig.github.io/pixi-viewport/
MIT License
1.04k stars 174 forks source link

Wheel and Drag interaction #415

Closed blnvdanil closed 1 year ago

blnvdanil commented 1 year ago

I want to implement the following functionality: zoom viewport on Ctrl+mouseWheel, and drag viewport on just mouseWheel.

My first implementation was listening Ctrl on window, and pause/resume Wheel and Drag plugins

// for ctrl keydown
() => {
    viewport.resume("wheel");
}
// for ctrl keyup
() => {
    viewport.pause("wheel");
}

And this solution works, except one case -- when window is not focused, in that case keyup and keydown events just do not fire. And I was wondering if it is possible to use event.ctrlKey property to determine if viewport should zoom or drag. It is possible to change code of checkKeyPress function in Wheel plugin to make it work the way I want. But there is still a problem, when Wheel plugin is applied, Drag plugin just can not drag viewport anymore. So maybe that is possible to change this condition to allow drag plugin do it's thing when, for example, Wheel plugin does not handle wheel event?

blnvdanil commented 1 year ago

Well, seems that I came up with a good solution for me, I implemented separate plugin, that uses Wheel and Drag plugins internally. Here is some code.

export class CustomWheelDrag extends Plugin {
  private wheelPlugin: Wheel;
  private dragPlugin: Drag;

  constructor(parent: Viewport) {
    super(parent);
    this.wheelPlugin = new Wheel(parent);
    this.dragPlugin = new Drag(parent);
  }

  public override wheel(event: WheelEvent): boolean | undefined {
    if (event.ctrlKey) {
      return this.wheelPlugin.wheel(event);
    }

    if (event.shiftKey && !this.dragPlugin.options.wheelSwapAxes) {
      this.dragPlugin.destroy();
      this.dragPlugin = new Drag(this.parent, { wheelSwapAxes: true });
    }

    if (!event.shiftKey && this.dragPlugin.options.wheelSwapAxes) {
      this.dragPlugin.destroy();
      this.dragPlugin = new Drag(this.parent);
    }

    return this.dragPlugin.wheel(event);
  }

}

I leave the redefinition of all other methods of Plugin outside the scope