I have an image that is and must have its anchor/origin point set to the upper left corner. It is a large image bigger than the screen and I want the ability to pan across it and zoom into the visible center. By default, the scaling collapses to the upper left as you zoom in. Simply put, I need to move the image after it scales to give the illusion that you zoomed into the center of the screen. I should also mention that scaling is a number between 0 and 1: 1x Zoom = 1 and 2x Zoom = .5

I stripped away the syntax to make things as clear as possible.

Here is the broken math I am currently using:

--Set vars
imageWidthNew = tileSize * mapData.gridW * scale
imageHeightOld = tileSize * mapData.gridH * mapGrp.yScale
imageHeightNew = tileSize * mapData.gridH * scale
screenWidth = 480
screenHeight = 320
--Get a number between 0 and 1 based position within bounds
pX = mapGrp.x / (imageWidthOld - screenWidth)
pY = mapGrp.y / (imageHeightOld - screenHeight)
--Set New Position
mapGrp.x = -pX * (screenWidth - imageWidthNew)
mapGrp.x = -pY * (screenHeight - imageHeightNew)

As I scale the image it collapses/expands from its local 0,0 (Top/Left) position. As a result you are 'zooming' into the objects local point 0,0 (the object's x/y value). I want to change the x/y position of the image to make it look like you are zooming into a specific point. That point should be determined by what is visible at the center of the screen. I need to get the same spot of the image to be in the center of the screen before and after the zoom. The problem is that I am unable to correct for the change as the image scales. If you need context, the image is actually a map made of tiles. I have the panning set and clicking working that uses the offset of the image to calculate what tile is being pressed and it works at all scales. The problem is strictly a display issue.

While I've understood your requirements (and guessed about the tiles), I failed to correctly link them with the posted code. For this very reason I asked you an example of IO (with actual numbers) as well of the expected output.

Sorry, for any confusion. Right now the function doesn't do much because I am just trying to scale and move a group. Here is what I have:

local setScale = function(scale) --Some values that can be used local imageWidthOld = tileSize * mapData.gridW * mapGrp.xScale local imageWidthNew = tileSize * mapData.gridW * scale local imageHeightOld = tileSize * mapData.gridH * mapGrp.yScale local imageHeightNew = tileSize * mapData.gridH * scale local screenWidth = 480 local screenHeight = 320

--Zoom mapGrp.x = --new mapGrp.x to offset scale mapGrp.y = --new mapGrp.y to offset scale

Here are some more ways the map is being used for added context:

local getTileID = function(r,c) return ((r - 1) * mapData.gridW) + c end local getTileCR = function(id) local r = math.ceil(id / mapData.gridW) local c = id - ((r-1) * mapData.gridW) return r,c end

local r = math.ceil((event.y - mapGrp.y) / (tileSize * mapGrp.yScale)) local c = math.ceil((event.x - mapGrp.x) / (tileSize * mapGrp.xScale)) local tileID = getTileID(r,c)

Numbers, numbers, I need actual numbers! Why do you say the math is wrong? Probably because for some inputs you don't get the expected output. Hence what is the input? What is the output. What is the expected output? (Sorry for the insistence)

local tileSize = 48 local gridH = 40 local gridW = 50 local screenWidth = 480 local screenHeight = 320

I understand where you are coming from, but that is all of the numbers. That is what I am working with and even that is technically just the value for a particular device. I have tried several formula, but I cannot get one that works. Lets think of it like this. I have a 2000 by 2000 image that is left aligned and at the coordinates -100,-50. I want to zoom into the center of the 480,320 screen by 200% and offset the image so that the same part of the image remains in the center. How do I answer that question? I think I attempted to do it wrong.

Thanks for the advice. I am just missing one more part to get this right, but it is much closer. I have it so that I can zoom from far left/right and top/bottom based on a number between 0 and 1. Now I just need to match that number up better. It currently works for the center, but has a bias toward the edge it is at. I just need to get it to add -1/4 on the left z0 at the center and 1/4 on the right.

Here is whet I currently have:

local setScale = function(scale) local deltaScale = scale - mapGrp.xScale local imageWidth = tileSize * mapData.gridW local imageHeight = tileSize * mapData.gridH

--This is a number between zero and one that needs to be improved local xPoint = mapGrp.x / xBound local yPoint = mapGrp.y / yBound

As I scale the image it collapses/expands from its local 0,0 (Top/Left) position. As a result you are 'zooming' into the objects local point 0,0 (the object's x/y value). I want to change the x/y position of the image to make it look like you are zooming into a specific point. That point should be determined by what is visible at the center of the screen. I need to get the same spot of the image to be in the center of the screen before and after the zoom. The problem is that I am unable to correct for the change as the image scales. If you need context, the image is actually a map made of tiles. I have the panning set and clicking working that uses the offset of the image to calculate what tile is being pressed and it works at all scales. The problem is strictly a display issue.

local setScale = function(scale)

--Some values that can be used

local imageWidthOld = tileSize * mapData.gridW * mapGrp.xScale

local imageWidthNew = tileSize * mapData.gridW * scale

local imageHeightOld = tileSize * mapData.gridH * mapGrp.yScale

local imageHeightNew = tileSize * mapData.gridH * scale

local screenWidth = 480

local screenHeight = 320

--Zoom

mapGrp.x = --new mapGrp.x to offset scale

mapGrp.y = --new mapGrp.y to offset scale

mapGrp.xScale= scale

mapGrp.yScale= scale

--Prevent map from moving beyond limits

xBound = (tileSize * mapData.gridW * mapGrp.xScale - 480) * -1

yBound = (tileSize * mapData.gridH * mapGrp.yScale - 320) * -1

applyMapBounds()

end

local getTileID = function(r,c)

return ((r - 1) * mapData.gridW) + c

end

local getTileCR = function(id)

local r = math.ceil(id / mapData.gridW)

local c = id - ((r-1) * mapData.gridW)

return r,c

end

local r = math.ceil((event.y - mapGrp.y) / (tileSize * mapGrp.yScale))

local c = math.ceil((event.x - mapGrp.x) / (tileSize * mapGrp.xScale))

local tileID = getTileID(r,c)

Why do you say the math is wrong? Probably because for some inputs you don't get the expected output. Hence what is the input? What is the output. What is the expected output?

(Sorry for the insistence)

local gridH = 40

local gridW = 50

local screenWidth = 480

local screenHeight = 320

I understand where you are coming from, but that is all of the numbers. That is what I am working with and even that is technically just the value for a particular device. I have tried several formula, but I cannot get one that works. Lets think of it like this. I have a 2000 by 2000 image that is left aligned and at the coordinates -100,-50. I want to zoom into the center of the 480,320 screen by 200% and offset the image so that the same part of the image remains in the center. How do I answer that question? I think I attempted to do it wrong.

all the coordinates are in the image space

xc = 240 + 100 = 340 // coordinates of the image point at center of the screen

yc = 160 + 50 = 210

xleft = 100 // coordinates of the image point at top-left of the screen

ytop = 50

zoom 2x ->

xleft' = (xleft + xc) / 2 = 220 // coordinates of the zoomed image point at top left of the screen

ytop' = (ytop + yc) / 2 = 130

Hence the (zoomed) image part on the screen is {220, 130, 459, 289}

Where xright' = xleft' + 480/2 -1 = 459

ybottom' = ytop' + 320/2 -1 = 289

That means image position change from {-100, -50} to (zoomed) {-220,-130}

Here is whet I currently have:

local setScale = function(scale)

local deltaScale = scale - mapGrp.xScale

local imageWidth = tileSize * mapData.gridW

local imageHeight = tileSize * mapData.gridH

--This is a number between zero and one that needs to be improved

local xPoint = mapGrp.x / xBound

local yPoint = mapGrp.y / yBound

mapGrp.x = mapGrp.x - (imageWidth * deltaScale * xPoint)

mapGrp.y = mapGrp.y - (imageHeight * deltaScale * yPoint)

mapGrp.xScale= scale

mapGrp.yScale= scale

xBound = (tileSize * mapData.gridW * mapGrp.xScale - 480) * -1

yBound = (tileSize * mapData.gridH * mapGrp.yScale - 320) * -1

applyMapBounds()

end