Jump to content
  • Advertisement
Sign in to follow this  
CelticSir

Problem with my zooming feature after panning

This topic is 1506 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey,

 

I have been trying to add a zoom feature to my game but was experiencing issues with scrolling after having zoomed in and out. I get this weird "snapping" movement.

 

I have managed to reproduce the glitch in a fiddle here http://jsfiddle.net/d3k0yg0b/

 

I'm not totally sure what is causing the problem but I've been trying to look at my logic all day and can't work out whats causing it. The two main functions related to the problem are below:

 

function scroll(e) { //mousedown event trigger
    e.preventDefault();
    var mousePos = {};
        mousePos.x = e.pageX;
        mousePos.y = e.pageY;
    var parent = this,
        offsetX = canvas.offsetX,
        offsetY = canvas.offsetY;

    function update(e) {
    var new_mousePos = {};
        new_mousePos.x = e.pageX;
        new_mousePos.y = e.pageY;
    var difx = new_mousePos.x - mousePos.x,
        dify = new_mousePos.y - mousePos.y;
        canvas.offsetX = offsetX + (difx / 2.5);
        canvas.offsetY = offsetY + (dify / 2.5);

    var max_x = (canvas.width / 2) + (radius / 2),
        min_x = (canvas.width / 2) - (radius / 2),
        max_y = (canvas.height / 2) + (radius / 2),
        min_y = (canvas.height / 2) - (radius / 2);

        if (canvas.offsetX > max_x) {
            canvas.offsetX = max_x;
        } else if (canvas.offsetX < min_x) {
            canvas.offsetX = min_x;
        }
        if (canvas.offsetY > max_y) {
            canvas.offsetY = max_y;
        } else if (canvas.offsetY < min_y) {
            canvas.offsetY = min_y;
        }
    }

    function clear() {
        parent.removeEventListener('mousemove', update, false);
        this.removeEventListener('mouseup', clear, false);
    }
    parent.addEventListener('mousemove', update, false);
    document.body.addEventListener('mouseup', clear, false);
}


function zoomTest(e){
    ////
    //update radius for circle
    ////
    function zoomUpt(){
        radius = modifyPercentage(init_radius,zoom.percent);
    }
    ////
    //animate zoom to make it smoother
    ////
    function transition_zoom(zoom,speed,fnc){
        if(zoom.intervalId != false){ 
            clear();
        }        
        var range = zoom.percentVal*zoom.modifier;
        
        if(zoom.direction == 1){
        var endVal = zoom.position + range;
            if(endVal > zoom.maxRange){
                endVal = zoom.maxRange;
            }
        }else if(zoom.direction == 0){
        var endVal = zoom.position - range;
            if(endVal < 50){
                endVal = 50;
            }
        }
        
        function process_transition(){
            if(zoom.direction){
                zoom.position += zoom.speed;
                if(zoom.position > zoom.maxRange){ zoom.position = zoom.maxRange; }
                if(zoom.position > endVal) { zoom.position = endVal;}    
            } else {	
                zoom.position -= zoom.speed;
                if(zoom.position < 50) { zoom.position = 50; } 
                if(zoom.position < endVal) { zoom.position = endVal;} 
            }
            zoom.percent = (zoom.position/zoom.range) * 100;		
            if(fnc){ 
                fnc();
            }			
            if(zoom.position == endVal){
                clear();
            }
        }
        
        function clear(){
            clearInterval(zoom.intervalId);
            zoom.intervalId = false;
        }
        zoom.intervalId   = setInterval(process_transition,1);
    } 
    ////
	var delta 	= e.wheelDelta,
	    oldZoom 	= zoom.position,
	    completed	= 0;

	if(delta == 120){ 		  //scroll in
	        zoom.direction = 1;
        } else if(delta == -120){         //scroll out
		zoom.direction = 0;
	} else {
		zoom.direction = -1;
	}
}	
    if(zoom.position == zoom.maxRange && zoom.direction){ return false; }
	if(zoom.position == 150 && !zoom.direction){ return false; }				
	transition_zoom(zoom,zoom.speed,zoomUpt);
}
Edited by thefollower

Share this post


Link to post
Share on other sites
Advertisement

Someone might see something, but nothing pops out at me as "the reason".

 

If this were my problem to solve, I would first factor out camera code - totally separate it from circle and world (canvas) logic. This separates the responsibility of each piece of code, and makes it far easier to debug, maintain, add on to, read, etc. Right now it's beginning to be spaghetti-y, and the potential is there to get much worse (thus harder to parse, use, fix, etc.).

Edited by achild

Share this post


Link to post
Share on other sites

The problem lies in the difference between your world and screen coordinates. You're creating a region in screen coordinates to keep your circle in place. But as you zoom in and out, that changes how those world coordinates map to screen coordinates.

Share this post


Link to post
Share on other sites

The problem lies in the difference between your world and screen coordinates. You're creating a region in screen coordinates to keep your circle in place. But as you zoom in and out, that changes how those world coordinates map to screen coordinates.

So what part should I have changed, as i have always found it confusing understanding world and screen coordinates.

Share this post


Link to post
Share on other sites

You're only simulating a camera zoom by changing the radius of your circle. It there were other shapes on the screen, they wouldn't be drawn appropriately. So technically it's not a world vs. screen coordinates problem, but it's similar.

 

Let's zoom it way in so the radius is 200 pixels. You then base your min/max_x/y variables on this radius so you're allowed to move it half-that (100) pixels in any direction. Let's move it left 100 pixels. Now let's zoom back out to where the circle is 20 pixels wide. Now you're only allowed to move it half-that (10) pixels in any direction. The next time you try to move it, it will jump 90 pixels to get back in the bounds of your box.

 

If you'd like to implement a 2D camera, here's a pretty good implementation for XNA/C#, but the concepts should be the same in any language.

http://stackoverflow.com/questions/712296/xna-2d-camera-engine-that-follows-sprite

 

Hope this helps,

- Eck

Share this post


Link to post
Share on other sites

I think i got it working seeing here:

http://jsfiddle.net/x6d9eo31/

 

Although having issues with the scroll when zoomed in far enough, i can't seem to get the camera to offset far enough to reach the perimeter of the circle. =/

Edited by thefollower

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!