Olololz

Pixi.JS / Pan & Zoom Canvas

Recommended Posts

Hi,

I'm using Pixi since several days on a game prototype which consists in a map made of tiles.

The problem is that I got a big map (2000px / 2000px), so it don't fit a desktop screen, and not any mobile screen.

I am looking for a way to allow the user to

  • pan (i.e. navigating on the canvas with mouse drag and drops (for desktop) and with the finger (for mobile devices)
  • zoom in / out the canvas

Like in google maps for example

Any idea of an embedded feature I can use?

 

Thanks in advance for you answers.

Share this post


Link to post
Share on other sites

It is implemented as 2D tramsformation, you need to build a 2D matrix with the ZOOM/PAN you made.

Here an example of an isometric matrix.

//position things on the stage
screenSpacePosition=new PIXI.Matrix(.5, .25,  -.5, .25, newOrigineX, newOrigineY).apply(workingSpacePosition);

//get back to the working space to make you usual things, for example do something when you catch a mouse click on the screen.
workingSpacePosition=new PIXI.Matrix(.5, .25,  -.5, .25,  newOrigineX, newOrigineY).applyInverse(screenSpacePosition);

PAN is easy enough, you just need to keep track of the position offset, start with that.

A smart ZOOM that zoom where you point at can be a bit of a nightmare at first if you are not used of 2D trandformations, start with a zoom button maybe.

Share this post


Link to post
Share on other sites

^^^ Don't do that.

Add a container, put everything there. Study how "container.position", "container.scale", "container.pivot" works. I mean, really study => read docs, then look at sources may be. I wont post solution here, I'm exhausted today.

Remember that matrices of child is multiplied by container's matrix.

Share this post


Link to post
Share on other sites

Hello. I am new to pixi and needed pan-zoom for what I am working on. I wrote a game engine (i.e. port of Cocos2Dx) in Dart a while back called Ranger and it was scenegraph based as well. I had created the matrix code about 6 or 7 years ago while learning JavaFX. I originally tried to figure it out while learning Piccolo but I didn't understand scenegraphs at the time...several years later and some deep learning and the world is completely different, LOL.

So I ported the pan-zoom matrix code from Ranger into a simple demo. All the demo does is show the bare minimum for panning an zooming using a matrix that "overrides" pixi's for any particular node. This is real code that does exact zooming as it operates directly on behalf of the node's transform. Anyway, the main algorithm is entirely in the zoom.ts file (literally in one method)...ooh as I mentioned, I am new to pixi and didn't realize that pixi had input library so excuse the input.ts class, it is redundant and will be removed from my real game, embarassed:blink:

WARNING the demo was thrown together in AngularCLI. Don't worry though the entire code is in three files: input.ts, zoom.ts and app.component.ts. All the rest of the files are bulk created by the angular-cli tool, but most importantly pay attention to zoom.ts as that is where the gist of the algorithm is, the rest is just support code for mouse, keyboard and stuff.

On a side note it does show how to make pixi work in Angular while avoiding Angular's event zones. The white text is the mouse's positional data mapped into various spaces. You can move the blue rectangle using the arrow keys. As a bonus the zoom and pan can be animated using Tweens if need be, I know because I was doing it in my engine, watch the triangle ship move in and out of zoom zones and you will get the idea:

https://plus.google.com/u/0/b/109136453872758385259/photos/photo/109136453872758385259/6068339953594223986?icm=false&iso=true

The repo for the demo is: https://github.com/wdevore/pixi-pan-zoom

Cheers.

pixi-pan-zoom.png

Share this post


Link to post
Share on other sites
7 hours ago, EndlessLife said:

Hello. I am new to pixi and needed pan-zoom for what I am working on. I wrote a game engine (i.e. port of Cocos2Dx) in Dart a while back called Ranger and it was scenegraph based as well. I had created the matrix code about 6 or 7 years ago while learning JavaFX. I originally tried to figure it out while learning Piccolo but I didn't understand scenegraphs at the time...several years later and some deep learning and the world is completely different, LOL.

You've certainly has some experience with 2d in different languages/platforms ;)

Share this post


Link to post
Share on other sites
3 hours ago, ivan.popelyshev said:

You've certainly has some experience with 2d in different languages/platforms ;)

Thanks Ivan,

I forgot to mention how the code works in conjunction pixi.

There is technically three ways you can manipulate pixi's container: inheritance, override the updateTransform() or overwrite a localTransform. I originally did the second option but didn't like the fact that I couldn't access any private or protected data. I ended up, for simplicity of the demo, going with option #3 and that is what you will see in the ticker callback which ultimately calls _updateZoom():

private _updateZoom() {
  const t = this.zoom.Transform;

  this.game.transform.localTransform.set(t.a, t.b, t.c, t.d, t.tx, t.ty);
  this.zoomContainer.transform.updateTransform(this.game.transform);
}

One thing to notice is that I create an outer Container node so I can control the update. "this.zoomContainer" contains "this.game", this is important because it gives me a "parent" that I can control when to perform a transform update. This is the one main concept that makes the code work, using .parent doesn't work because you end up trying to update "yourself".

The scenegraph looks like this:

  • stage
    • zoomContainer
      • game
        • blueRect
        • orangeRect
        • cursorRect
    • overlay
      • text

Funny, there is more code man-handling the mouse than there is zoom code, lol. In the long run I would probably use option #2 and extend the Container class to create a new node called, say, ZoomContainer.

Share this post


Link to post
Share on other sites
const app = new PIXI.Application()

// add a bunch of stuff to the app.stage, some of which is off screen

// later, in the pan function
app.stage.x = -100
app.stage.y = -100

// later in the zoom function
app.stage.scale.x = 1.5
app.stage.scale.y = 1.5

app.stage.x = -150 // got to update these to keep the center point from moving!
app.stage.y = -150

 

Is there anything wrong with doing the pan and zoom manually like above? I'm adapting a game from a hand built graphics engine into pixi and the above seems to work just fine. I just wanted to check for obvious pitfalls and (if none) leave it here for others to see.

Share this post


Link to post
Share on other sites

Excellent question Chris Cauley,

The code you are showing will work only as long as the zoom focal point doesn't more. Every time the focal point moves the views jerks.

With panning/zooming the focal point will move all over the place which means you needs to maintain state. The zoom.ts does just that via an accumulation matrix. I have used this extension approach in several engines including JavaFX, Piccolo, my Dart engine, a software engine and now Pixi 😉 

Cheers.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.