Advertisement

Problem with my zooming feature after panning

Started by October 24, 2014 02:32 AM
4 comments, last by CelticSir 10 years, 3 months ago

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);
}

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.).

Advertisement

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.

EckTech Games - Games and Unity Assets I'm working on
Still Flying - My GameDev journal
The Shilwulf Dynasty - Campaign notes for my Rogue Trader RPG

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.

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

EckTech Games - Games and Unity Assets I'm working on
Still Flying - My GameDev journal
The Shilwulf Dynasty - Campaign notes for my Rogue Trader RPG

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. =/

This topic is closed to new replies.

Advertisement