Jump to content

"Zooming into" a specific point.


Recommended Posts

Hello,

 

I understand that we can "zoom" into a displayObjectContainer using the 'scale' property. I currently have one large such container which contains all of my graphics. However, on increasing the scale point, the screen zooms into the top left corner of the screen (presumably some kind of anchor point?). Is there any way to have the screen scale towards a specific point or anchor? i.e Zooming into the cursor position for example. At the moment, the displayObjectContainer seems to have no anchor property.

 

ie. (Can we achieve a 'zoom' into a specific x/y point?) or even just a decimal anchor point of some sort?

 

Much appreciated,

Jordan

Link to post
Share on other sites

Here how I zoom to mouse position by wheel. The accuracy is not perfect, but it resolves my task

 

var doc = new PIXI.DisplayObjectContainer;var canvas = $('canvas');//Bind eventcanvas.bind('wheel', function (e) {    if (e.originalEvent.deltaY < 0) {        zooming(1, e.originalEvent.pageX, e.originalEvent.pageY);    } else {        zooming(-1, e.originalEvent.pageX, e.originalEvent.pageY);    }});function zooming(zoom, x ,y) {    //Current scale    var scale = doc.scale.x;    //Mouse position    var mouse = new PIXI.Point(x,y);    //Mouse position relative to DisplayObjectContainer    var point = doc.toLocal(mouse);    //zooming    if (zoom > 0) {        if (scale < SCALE_MAX) {            scale += 0.1;                        //moving            doc.position.set(-point.x / 7, -point.y / 7)        }    } else {        if (scale > SCALE_MIN) {            scale -= 0.1;            //moving            doc.position.set(point.x / 7, point.y / 7)        }    }    doc.scale.set(scale, scale);}
Link to post
Share on other sites

Hi Guys, 

 

An update as to where I am so far. I currently have the following code:

 

Using jquery-mousewheel plugin:

masterContainer is declared before this script and is the displayObjectContainer containing the game world.

 

I'm using .toFixed() to reduce floating-point number inconsistencies.

<script>		// Set initial mouse position		var mousePos = {x:0, y:0};		// Document ready block			$( document ).ready(function() {	   							// Set update of mouse co-ords and panning on mouse move	   			$(document).mousemove(function(event) {	        			mousePos.x = event.pageX;	        			mousePos.y = event.pageY;				});	   			//Set zooming capability on scroll wheel use	   			$(document).mousewheel(function(event) {				    switch(event.deltaY)				    {				    	case 1 || 2 || 3 || 4 || 5:				    	// Get the current mouse x and mouse y				    	// We need to zoom in, and then move the world so that we are focusing on the same tile				    	console.log("Zoomed In");				    	masterContainer.pivot.x = mousePos.x;				    	masterContainer.pivot.y = mousePos.y;						masterContainer.x = mousePos.x;						masterContainer.y = mousePos.y;				    	masterContainer.scale.x = (masterContainer.scale.x * 1.25).toFixed(1);				    	masterContainer.scale.y = (masterContainer.scale.y * 1.25).toFixed(1);				    	break;				    	case -1:				    	console.log("Zoomed Out");				    	masterContainer.scale.x = (masterContainer.scale.x / 1.25).toFixed(1);				    	masterContainer.scale.y = (masterContainer.scale.y / 1.25).toFixed(1);				    	break;				    }				});	   		});	</script>

This code doesn't account for zoom acceleration (number of scroll wheel 'clicks') but, on the surface of things, performs well.

However, a problem occurs when the scale > 1x as the x/y co-ords then correspond to different points than when the object container was sitting at 1x zoom.

 

e.g. Zooming in to a point on-screen, and then moving the mouse to zoom over another part of the screen (and zooming) - (whilst still zoomed in) causes unexpected behaviour due to the change in x.y co-ords.

So; i'm currently looking into how I can work out "where stuff is" when the zoom (or scale) is greater than 1. 

 

Turns out that this isn't such a trivial task!

Link to post
Share on other sites

I think pivot is not useful here, as it's not fixed in this case and you'd need to do some confusing math when you change it...

 

Here's the code I use for zooming:

    screenToWorld: function (p) {        return {            x: this.position.x + p.x / this.scale,            y: this.position.y + p.y / this.scale        }    },     worldToScreen: function (p) {        return {            x: (p.x - this.position.x) * this.scale,            y: (p.y - this.position.y) * this.scale        }    },        zoom: function (zoomLocationScreen, zoomScale) {     //get the world coordinates of the zoom location        var zoomLocationWorld = this.screenToWorld(zoomLocationScreen);                //change scale, clamp it between minScale/maxScale        this.scale = Math.max(Math.min(this.scale * zoomScale, this.maxScale), this.minScale);                //where is the zoom location now, after we changed the scale?        var newZoomLocationScreen = this.worldToScreen(zoomLocationWorld);                //move the world so that the zoomed-location goes back to where it was on the screen before scaling        this.position.x += (newZoomLocationScreen.x - zoomLocationScreen.x) / this.scale;        this.position.y += (newZoomLocationScreen.y - zoomLocationScreen.y) / this.scale;    } 
Link to post
Share on other sites

Hm, setting the pivot will 'offset' the DOC, so you simple need to set the x/y to the same coordinates, which sounds simpler, but maybe I'm missing something here.

 

Hi @digibo,

 

The problem comes that this is only good when scale is (1=1). As soon as you scale up, the x/y co-ords no longer correspond to the same places.

Link to post
Share on other sites

 

Here how I zoom to mouse position by wheel. The accuracy is not perfect, but it resolves my task

 

var doc = new PIXI.DisplayObjectContainer;var canvas = $('canvas');//Bind eventcanvas.bind('wheel', function (e) {    if (e.originalEvent.deltaY < 0) {        zooming(1, e.originalEvent.pageX, e.originalEvent.pageY);    } else {        zooming(-1, e.originalEvent.pageX, e.originalEvent.pageY);    }});function zooming(zoom, x ,y) {    //Current scale    var scale = doc.scale.x;    //Mouse position    var mouse = new PIXI.Point(x,y);    //Mouse position relative to DisplayObjectContainer    var point = doc.toLocal(mouse);    //zooming    if (zoom > 0) {        if (scale < SCALE_MAX) {            scale += 0.1;                        //moving            doc.position.set(-point.x / 7, -point.y / 7)        }    } else {        if (scale > SCALE_MIN) {            scale -= 0.1;            //moving            doc.position.set(point.x / 7, point.y / 7)        }    }    doc.scale.set(scale, scale);}

 

Hi, what's the purpose of the divide by seven when re-positioning the game world?

Link to post
Share on other sites
  • 5 months later...

Just in case someone is looking for this, I tried some of the zoom implementations of this post but they did not work for me. I think the problem is that the stage.x,stage.y values that PIXI.js reports are not scaled with stage.scale.x,stage.scale.y.

Here is my implementation that also adds a correction to the stage.x, stage.y that is related to the differences of scales, I'm not quite sure about this correction may be someone can explain why it works  :)

http://plnkr.co/edit/II6lgj511fsQ7l0QCoRi?p=preview

It works pretty well for medium scales.

Cheers

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...