pixi-viewport icon indicating copy to clipboard operation
pixi-viewport copied to clipboard

How to center the viewport when the resolution != 1.0 ?

Open peekxc opened this issue 1 year ago • 3 comments

I cannot figure out how to get everything centered and scaled directly, it's a total nightmare.

I just want to move the viewport to be centered at some fixed location. That's all.

However, unless I supply a resolution of 1.0, none of the expected coordinate transforms work.

Here's an example showing this:

<!DOCTYPE html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="description" content="">
    <meta name="theme-color" content="#000000">
  </head>
  <body>
  <script type="module">
    import { Application, Graphics, GraphicsContext } from 'pixi.js'
    import { Viewport } from 'pixi-viewport';
  
    const app = await new Application();
    await app.init({ 
      autoResize: false, 
      background: 0xededed,
      autoStart: false,
      transparent: false, 
      resolution: 1.0,  // <- this has to be 1 for centering to work, but I prefer devicePixelRatio
      antialias: true, 
      forceCanvas: false,
    });
    let canvas = app.canvas
    app.renderer.resize(1200,800,1.0) // <- this has to be 1 for centering to work
    canvas.width = 1200;
    canvas.height = 800;
    document.body.appendChild(canvas);
  
    let viewport = new Viewport({
      worldWidth: canvas.width,
      worldHeight: canvas.height,
      passiveWheel: false, 
      events: app.renderer.events,
    });
    viewport.drag().wheel(1e-3).decelerate();
    viewport.fit()
  
    // Construct some random nodes
    let node_context = new pn.GraphicsContext()
      .circle(0, 0, 6)
      .stroke({ width: 1.5, color: 0xFFFFFF })
      .fill({ color: 0x650A5A });
  
    // Add the random nodes to the viewport
    for (let i = 0; i < 300; i++){
      let node = new pn.Graphics(node_context);
      node.x = Math.random() * app.renderer.width; 
      node.y = Math.random() * app.renderer.height; 
      viewport.addChild(node);
    }
  
    // This should be at the center of the viewport!
    let node_c = new pn.Graphics()
      .circle(0, 0, 6)
      .stroke({ width: 1.5, color: 0xFFFFFF })
      .fill({color: 0x000000 });
    node_c.x = 600; 
    node_c.y = 400; 
    viewport.addChild(node_c);
  
    app.stage.addChild(viewport);
    app.start();
    viewport.moveCenter(600, 400); // <- this doesnt work
</script>
</body>

peekxc avatar Dec 20 '24 19:12 peekxc

I'm having the same problems with .fit. Is any body working on this bug? If not I can try to figure it out.

FelixMo42 avatar Dec 23 '24 21:12 FelixMo42

Ahh, I've figured out a lot now.

You need to start the pixi application w/ autoDensity = true. This automatically handles the resolution and scaling needed for High DPI screens. Then, inspired by the app.js of the example, normalize the coordinates with:

this.view.style.width = this.width
this.view.style.height = this.height
this.view.style.left = 0
this.view.style.top = 0

where width and height are the actual canvas width and height attributes, respectively. This seems to make it such that all graphics and plotting need only to work in either the nice and simple 'screen' or 'world' coordinate systems---no manual adjusting for pixel ratios. moveCenter now works in this setting with world coordinates.

peekxc avatar Feb 04 '25 15:02 peekxc

@peekxc what is this.view and this.width in your example?

Fuzzyma avatar Apr 14 '25 09:04 Fuzzyma