• Status: Solved
• Priority: Medium
• Security: Public
• Views: 467

# Image viewer with zoom and pan, image won't center to correct area on zoom in or out

I've got an image viewer I'm making, it pans fine, but when zooming, it doesn't center correctly on the area the user was attempting to zoom into. Basically the problem is that when the image is shrunk, the upper left hand corner index stays the same, so when zooming out the bottom right hand corner goes up and left, and the reverse on zoom in. I tried using this (psuedocode version here)

if (new_size > old_size) {
};
if (new_size < old_size) {
};

and then simply add or subtract adjustindex from the x,y index of the upper left of the bitmap. It doesn't seem to work, though. Any idea what I'm missing?
0
zamfir1970
• 2
• 2
2 Solutions

Commented:
check out http://www.cleverpig.com/flashstuff.htm for the panorama example

Billystyx
0

Software developerCommented:
Hello,  zamfir1970!

Zooming is an affine space transformation. Transformations are performing relatively of a base point. When you simple zooming Flash's document by means of setting X_SCALE and Y_SCALE properties with using TSetProperty function, implicitly you are using scaling matrix  (sx, 0, 0, sy, 0, 0). This is default scaling matrix, therefore the last two elements are zeros. The meaningful value of these elements - is shift on X and Y axises.  Zooming relatively (0,0) causes shifting which should be compensated. Notice, the base point is immovable. Therefore, you should perform zooming relatively center of the Flash's curent view instead of (0, 0). You can go by two ways:
1) build complex transformation matrix:  M1 x Z x M2 (where: M1 - shifts view's center to the (0,0); Z - scales relatively (0,0); M2 - shifts view's center back);
2) zoom current view's center and calculate (deltaX, deltaY) values; after zooming add shift (-deltaX, -deltaY) to the current shift of the Flash's document.

I do not know how to calculate the bounding box of the current view (i am finding out this question now), but i had implemented code in order to calculate coordinates of current view's center. This looks like:

var f = document.getElementById( "idFlashPlayer" ); //in Microsoft Internet Explorer it is <object> tag with id="idFlashPlayer"
var currScale = 1;
var shX = 0, shY = 0;

function onZoomOut()
{
var cx1 = getCenX(), cy1 = getCenY();

currScale /= 1.5;
putZoom( currScale );

compensateShift( cx1, cy1, getCenX(), getCenY() );
putShift( shX, shY );
}
function onZoomIn()
{
var cx1 = getCenX(), cy1 = getCenY();

currScale *= 1.5;
putZoom( currScale );

compensateShift( cx1, cy1, getCenX(), getCenY() );
putShift( shX, shY );
}

function putZoom( newZoom )
{
var zoom = Math.round( newZoom * 100.0 );
f.TSetProperty( "/", 2, zoom );
f.TSetProperty( "/", 3, zoom );
}
function compensateShift( cx1, cy1, cx2, cy2 )
{
shX = shX + (cx2 - cx1) * currScale;
shY = shY + (cy2 - cy1) * currScale;
}
function putShift( shx, shy )
{
f.TSetProperty( "/", 0, Math.round(shx) );
f.TSetProperty( "/", 1, Math.round(shy) );
}

function getCenX()
{
var v = pixelsWidthToFlashNotScaled( clientWidth() );
return (v/2.0 - shX) / currScale;
}
function getCenY()
{
var v = pixelsHeightToFlashNotScaled( clientHeight() );
return (v/2.0 - shY) / currScale;
}

function clientWidth()
{
return f.clientWidth;
}
function clientHeight()
{
return f.clientHeight;
}

function pixelsWidthToFlashNotScaled( v )
{
return v * 1.6;
}
function pixelsHeightToFlashNotScaled( v )
{
return v * 2.9;
}

You can see, i found magic coefficients 1.6 and 2.9 which are permitting to convert coordinates from HTML's pixels to Flash's document. This is a partial and inaccurate solution. If better solution will be found i will notify you.

0

Author Commented:
This didn't really work for me, but I'm continuing to play with my version. I'm thinking that I need to move the image (in a movieclip) by the "handle" rather than by the index. when the handle is moved, I re-center the handle to the center of the stage, 200,200. I think this will work. I haven't tried it yet, though.
0

Software developerCommented:
Compensating shifts should be calculated relative current view. View is determined by "Flash viewer:'s window. In order to hold in place current view unmoveable during zooming (+/-), you should always hold in place view's center projection to Flash-document unmoveable.

1. Calculate view's center:
var f = document.getElementById( "idFlash" );
var cx1 = f.clientWidth() / 2, cy1 = f.clientHeight() / 2;

2. Translate cx, cy into Flash's coordinates:
var cxF1 = toFlash2X( cx ), cyF1 = toFlash2Y( cy );

function toFlash2X( val )
{
return (-f.TGetPropertyAsNumber("/", 0) + val) / f.TGetPropertyAsNumber( "/", 2)/100.0;
}
function toFlash2Y( val )
{
return (-f.TGetPropertyAsNumber("/", 1) + val) / f.TGetPropertyAsNumber( "/", 3)/100.0;
}

3. Change zoom-factor and repeat STEP2 - claculate again: var cxF2 = toFlash2X( cx ), cyF2 = toFlash2Y( cy ).

4. Compensate shifts, caused by zooming:

var newShX = f.TGetPropertyAsNumber("/", 0) + (cxF2 - cxF1) * f.TGetPropertyAsNumber( "/", 2)/100.0;
var newShY = f.TGetPropertyAsNumber("/", 1) + (cyF2 - cyF1) * f.TGetPropertyAsNumber( "/", 3)/100.0;

f.TSetProperty( "/", 0, newShX.toString() );
f.TSetProperty( "/", 1, newShY.toString() );

Now view's center is unmoveable during any zooming.

Look my discussion at: http://www.experts-exchange.com/Web/WebDevSoftware/Flash/Q_21396175.html. Go to my latest comment: full source code (in Java Script) is available here.

Do you have questions? Feel free to ask.
0

Author Commented:
Ah ok, I tried this and it works. We have a winner!

Thanks
0

## Featured Post

• 2
• 2
Tackle projects and never again get stuck behind a technical roadblock.