davidfig/pixi-viewport

Pixiv7+ out of box zoom not working

MatthewNicastro opened this issue · 0 comments

I have a very simple function that initializes a viewport instance and activates the wheel plugin aswell as the drag plugin. It seems that the out of box zoom implementation is not working. Initially I though it was just my environment however it seems that in other environments it also doesn't work.
Bellow is implementation

export const initImageViewport = (args: ImageViewportArgs) => {
  const { renderer, screenWidth, screenHeight, worldWidth, worldHeight, threshold, imgSrc } = args;
  const viewport = new Viewport({
    events: renderer.events,
    worldWidth,
    worldHeight,
    passiveWheel: false,
  });
  viewport.wheel().drag();
  const sprite = new Sprite(Texture.from(imgSrc));
  viewport.fit();
  viewport.moveCenter(worldWidth / 2, worldHeight / 2);
  viewport.addChild(sprite);
  for (let i = 0; i < 10000; i++) {
    const line = viewport.addChild(new Graphics());
    line.lineStyle(10, 0xff0000).drawRect(0, 0, viewport.worldWidth, viewport.worldHeight);
  }
  return viewport;
};

However when I check the wheel event it does fire, so I have to implement the zoom manually as follows

viewport.on('wheel', (event) => {
    const { client, deltaY } = event;
    const direction = -Math.sign(deltaY);
    const scale = 0.1;
    const scaleFactor = direction * scale;
    const { x: mouseWorldX, y: mouseWorldY } = viewport.toWorld(client.x, client.y);
    viewport.children.forEach((sprite) => {
      const scaleX = Math.max(sprite.scale._x + scaleFactor, 0.5);
      const scaleY = Math.max(sprite.scale._y + scaleFactor, 0.5);
      const before = sprite.width;
      sprite.scale.set(scaleX, scaleY);
      const after = sprite.width;
      const factor = after / before;
      const dx = (mouseWorldX - sprite.x) * (factor - 1);
      const dy = (mouseWorldY - sprite.y) * (factor - 1);
      sprite.x -= dx;
      sprite.y -= dy;
    });
  });

any suggestions on how i can not implement this by hand?

Update replaced the old wheel even with this new one which uses the viewport directly

// scale
  viewport.on('wheel', (event) => {
    const { client, deltaY } = event;
    const direction = -Math.sign(deltaY);
    // Calculate new scale factor
    let scaleFactor = viewport.scale._x + deltaScale * direction;
    // Clamp scale factor between min and max scale values
    scaleFactor = Math.max(scaleFactor, minScale);
    scaleFactor = Math.min(scaleFactor, maxScale);
    const before = viewport.width;
    viewport.setZoom(scaleFactor);
    const after = viewport.width;
    const factor = after / before;
    viewport.x -= (client.x - viewport.x) * (factor - 1);
    viewport.y -= (client.y - viewport.y) * (factor - 1);
  });