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

drag with space and left mouse OR middle mouse #467

Open MartinMouritzen opened 11 months ago

MartinMouritzen commented 11 months ago

Hi,

Thanks for a great tool. I'm building a "whiteboard" app where I'm coming from Konva.

I love the out-of-the-box options that viewport comes with, but I find myself unable to find a way to do a "OR". I would really like something like the following code, as in: pan the board with either space down and left mouse button OR the middle mouse button, which is the standard in almost all "board"/graphical apps. Am I missing some obvious way of doing it? :)

viewport .drag({ mouseButtons: 'left', keyToPress: 'Space' }) .drag({ mouseButtons: 'middle' })

blnvdanil commented 11 months ago

You can create your own plugin, which will hanlde that, just create an instance of a drag plugin inside of it, and proxy calls of corresponding methods, I did something similar for wheel and drag plugins interoperability

https://github.com/davidfig/pixi-viewport/issues/415

RATIU5 commented 8 months ago

I wanted to accomplish the same thing. I managed to figure out a working solution via a plugin from what @blnvdanil has stated previously.

import { Drag, Plugin, Viewport } from "pixi-viewport";
import { FederatedPointerEvent } from "pixi.js";

export class CustomDragPlugin extends Plugin {
  private spacePressed: boolean;
  private dragPlugin: Drag;
  private windowEventHandlers: Array<{ event: string; handler: (e: any) => void }> = [];

  constructor(viewport: Viewport) {
    super(viewport);
    this.spacePressed = false;
    this.dragPlugin = new Drag(viewport);

    this.handleKeyPresses();
  }

  public override down(event: FederatedPointerEvent): boolean {
    if (event.button === 1) {
      return this.dragPlugin.down(event);
    }
    if (this.spacePressed && event.button === 0) {
      return this.dragPlugin.down(event);
    }
    return false;
  }

  public override move(event: FederatedPointerEvent): boolean {
    return this.dragPlugin.move(event);
  }

  public override up(event: FederatedPointerEvent): boolean {
    return this.dragPlugin.up(event);
  }

  private handleKeyPresses(): void {
    const keydownHandler = (e: KeyboardEvent) => {
      if (e.code === "Space") {
        this.spacePressed = true;
      }
    };

    const keyupHandler = (e: KeyboardEvent) => {
      if (e.code === "Space") {
        this.spacePressed = false;
      }
    };

    this.addWindowEventHandler("keyup", keyupHandler);
    this.addWindowEventHandler("keydown", keydownHandler);
  }

  private addWindowEventHandler(event: string, handler: (e: any) => void): void {
    if (typeof window === "undefined") return;
    window.addEventListener(event, handler);
    this.windowEventHandlers.push({ event, handler });
  }

  public override destroy(): void {
    if (typeof window === "undefined") return;
    for (const { event, handler } of this.windowEventHandlers) {
      window.removeEventListener(event, handler);
    }
  }
}