How do I zoom in to mouse location accounting anchor point?

I have a function that zooms in a frame using UIScale, but it depends on anchor point. I have no idea how to make it zoom properly into mouse location.

function updateMainBoxZoom(v, czv, i)
	if typeof(v) == "boolean" then
		czv = czv or zoomPercentMin
		local zv = (czv + (zoomPercentMax - czv) * (zoom / maxZoom))
		if v == false then
			zv = -zv
		end
		v = zoom + zv
	end
	v = math.clamp(v, minZoom, maxZoom)
	zoom = v
	zoomFrame.ZoomOutButton.ZoomLabel.Text = "🔎 " .. (math.floor(zoom * 10) / 10)
	local lastV = mainBoxUIScale.Scale
	if lastV == v then
		return
	end
	if i == true then
		mainBoxUIScale.Scale = v
		return
	end

	local mousePosition = UDim2.fromOffset(math.floor(mouse.X - mainFrameBox.Position.X.Offset), math.floor(mouse.Y - mainFrameBox.Position.Y.Offset))
	local x1 = mousePosition.X.Offset * (zoom / lastV)
	local y1 = mousePosition.Y.Offset * (zoom / lastV)
	local x2 = mainFrameBox.Position.X.Offset + (mousePosition.X.Offset - x1)
	local y2 = mainFrameBox.Position.Y.Offset + (mousePosition.Y.Offset - y1)

	mainFrameBox.Position = UDim2.new(0, x2, 0, y2)

	mainBoxUIScale.Scale = v

	updatePixelHover()
end

When I first start zooming with this code, it moves the frame incorrectly because anchor point is 0.5, 0.5 but it works fine with 0, 0. I need it to be centered however, that’s why I use anchor point.

To zoom into the mouse location properly, you need to adjust the position of the frame relative to the mouse position before and after the zoom.

Try this new code:

function updateMainBoxZoom(v, czv, i)
if typeof(v) == “boolean” then
czv = czv or zoomPercentMin
local zv = (czv + (zoomPercentMax - czv) * (zoom / maxZoom))
if v == false then
zv = -zv
end
v = zoom + zv
end
v = math.clamp(v, minZoom, maxZoom)
zoom = v
zoomFrame.ZoomOutButton.ZoomLabel.Text = ":mag_right: " … (math.floor(zoom * 10) / 10)
local lastV = mainBoxUIScale.Scale
if lastV == v then
return
end
if i == true then
mainBoxUIScale.Scale = v
return
end

local mousePosition = UDim2.fromOffset(mouse.X - mainFrameBox.AbsolutePosition.X, mouse.Y - mainFrameBox.AbsolutePosition.Y)
local scaleChange = v / lastV
local newOffsetX = mousePosition.X.Offset - (mousePosition.X.Offset * scaleChange)
local newOffsetY = mousePosition.Y.Offset - (mousePosition.Y.Offset * scaleChange)

mainFrameBox.Position = UDim2.new(0, mainFrameBox.Position.X.Offset + newOffsetX, 0, mainFrameBox.Position.Y.Offset + newOffsetY)
mainBoxUIScale.Scale = v

updatePixelHover()

end

It’s now always offset

strokeskey

function updateMainBoxZoom(v, czv, i)
    if typeof(v) == "boolean" then
        czv = czv or zoomPercentMin
        local zv = (czv + (zoomPercentMax - czv) * (zoom / maxZoom))
        if v == false then
            zv = -zv
        end
        v = zoom + zv
    end
    v = math.clamp(v, minZoom, maxZoom)
    zoom = v
    zoomFrame.ZoomOutButton.ZoomLabel.Text = "🔎 " .. (math.floor(zoom * 10) / 10)

    local lastV = mainBoxUIScale.Scale
    if lastV == v then
        return
    end

    if i == true then
        mainBoxUIScale.Scale = v
        return
    end

    
    local mouseOffsetX = mouse.X - mainFrameBox.Position.X.Offset
    local mouseOffsetY = mouse.Y - mainFrameBox.Position.Y.Offset
    local mousePosition = UDim2.fromOffset(mouseOffsetX, mouseOffsetY)
    

    local scaleRatio = zoom / lastV

    
    local newPosX = mainFrameBox.Position.X.Offset - (mouseOffsetX * (scaleRatio - 1))
    local newPosY = mainFrameBox.Position.Y.Offset - (mouseOffsetY * (scaleRatio - 1))

    mainFrameBox.Position = UDim2.new(0, newPosX, 0, newPosY)

    
    mainBoxUIScale.Scale = v

    updatePixelHover()
end

Try this

It’s same as it was on the video

If the anchor point is centered at 0.5, 0.5, this means that the magnification must be adjusted so that the frame remains centered relative to the anchor point

function updateMainBoxZoom(v, czv, i)
    if typeof(v) == "boolean" then
        czv = czv or zoomPercentMin
        local zv = (czv + (zoomPercentMax - czv) * (zoom / maxZoom))
        if v == false then
            zv = -zv
        end
        v = zoom + zv
    end
    v = math.clamp(v, minZoom, maxZoom)
    zoom = v
    zoomFrame.ZoomOutButton.ZoomLabel.Text = "🔎 " .. (math.floor(zoom * 10) / 10)

    local lastV = mainBoxUIScale.Scale
    if lastV == v then
        return
    end

    if i == true then
        mainBoxUIScale.Scale = v
        return
    end

   
    local scaleRatio = zoom / lastV

    
    local mouseOffsetX = mouse.X - mainFrameBox.AbsolutePosition.X
    local mouseOffsetY = mouse.Y - mainFrameBox.AbsolutePosition.Y

  
    local anchorX = mainFrameBox.AnchorPoint.X
    local anchorY = mainFrameBox.AnchorPoint.Y
    local centerX = mainFrameBox.AbsoluteSize.X * anchorX
    local centerY = mainFrameBox.AbsoluteSize.Y * anchorY

    local newPosX = mainFrameBox.Position.X.Offset - (mouseOffsetX - centerX) * (scaleRatio - 1)
    local newPosY = mainFrameBox.Position.Y.Offset - (mouseOffsetY - centerY) * (scaleRatio - 1)

    mainFrameBox.Position = UDim2.new(0, newPosX, 0, newPosY)

    
    mainBoxUIScale.Scale = v

    updatePixelHover()
end

This works now but 0s should be replaced with anchor point

mainFrameBox.Position = UDim2.new(anchorX, newPosX, anchorY, newPosY)

To ensure that the mainFrameBox remains correctly centered relative to the anchor point and that it zooms correctly based on that point

function updateMainBoxZoom(v, czv, i)
    if typeof(v) == "boolean" then
        czv = czv or zoomPercentMin
        local zv = (czv + (zoomPercentMax - czv) * (zoom / maxZoom))
        if v == false then
            zv = -zv
        end
        v = zoom + zv
    end
    v = math.clamp(v, minZoom, maxZoom)
    zoom = v
    zoomFrame.ZoomOutButton.ZoomLabel.Text = "🔎 " .. (math.floor(zoom * 10) / 10)

    local lastV = mainBoxUIScale.Scale
    if lastV == v then
        return
    end

    if i == true then
        mainBoxUIScale.Scale = v
        return
    end

    
    local scaleRatio = zoom / lastV

    
    local absPosX = mainFrameBox.AbsolutePosition.X
    local absPosY = mainFrameBox.AbsolutePosition.Y
    local absSizeX = mainFrameBox.AbsoluteSize.X
    local absSizeY = mainFrameBox.AbsoluteSize.Y

    
    local anchorX = mainFrameBox.AnchorPoint.X
    local anchorY = mainFrameBox.AnchorPoint.Y
    local centerX = absPosX + absSizeX * anchorX
    local centerY = absPosY + absSizeY * anchorY

    
    local mouseOffsetX = mouse.X - absPosX
    local mouseOffsetY = mouse.Y - absPosY

    
    local newPosX = absPosX - (mouseOffsetX - centerX) * (scaleRatio - 1)
    local newPosY = absPosY - (mouseOffsetY - centerY) * (scaleRatio - 1)

    mainFrameBox.Position = UDim2.new(0, newPosX, 0, newPosY)

    
    mainBoxUIScale.Scale = v

    updatePixelHover()
end

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.