Use mouse to zoom in and out on a frame

I’ve searched so many posts and none of it has what i want,
An example video is on this post.
I have a canvas frame that I want to zoom in/out on using the mouse. I can scale it using Frame.Size += UDim2.fromOffset(100 * direction, 100 * direction) with direction as math.sign(inputObject.Position.Z), but I can’t seem to position it correctly. I want it to be positioned relative to the mouse so that when you zoom, the pixel you were hovering over is the same one just moved and scaled

Paint 3D kinda has what I want, although sometimes it does just jump around

You would probably have to incorporate the coordinates of the player’s mouse on the screen into your code. These coordinates could be found using:

local mouse = plr:GetMouse()
local mouseX = mouse.X
local mouseY = mouse.Y
1 Like

i figured it out

local UIS = game:GetService("UserInputService")

local plr = game.Players.LocalPlayer
local mouse = plr:GetMouse()

local Frame = script.Parent
local viewportSize = Frame:FindFirstAncestorWhichIsA("ScreenGui").AbsoluteSize
Frame.Position = UDim2.new(0,viewportSize.X/2,0,viewportSize.Y/2) -- center of screen

local ZOOM_SPEED = 10

UIS.InputChanged:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseWheel then
		local zoomFactor = ZOOM_SPEED/100
		
		local mouseX = mouse.X
		local mouseY = mouse.Y
		local direction = input.Position.Z
		
		local middle = Vector2.new(Frame.Position.X.Offset,Frame.Position.Y.Offset)
		local frameX = Frame.Size.X.Offset
		local frameY = Frame.Size.Y.Offset

		local relativeEdgeX = -frameX/2
		local relativeMouseX = mouseX - middle.X
		local scaleFactorX = relativeMouseX/relativeEdgeX
		
		local relativeEdgeY = -frameY/2
		local relativeMouseY = mouseY - middle.Y
		local scaleFactorY = relativeMouseY/relativeEdgeY
		
		Frame.Size += UDim2.fromOffset(zoomFactor * frameX * direction, zoomFactor * frameY * direction)
		Frame.Position += UDim2.fromOffset(direction * (zoomFactor * frameX/2) * scaleFactorX, direction * (zoomFactor * frameX/2) * scaleFactorY)
	end
end)
2 Likes

This one didn’t work for me, I made my own solution with scaling around the AnchorPoint:

local UserInputService = game:GetService("UserInputService")
local Frame = script.Parent

local ZoomAmount = 50
local MinimumSize = Frame.AbsoluteSize/3
local MaximumSize = Frame.AbsoluteSize*2.5

UserInputService.InputChanged:Connect(function(inputObject)
	if inputObject.UserInputType == Enum.UserInputType.MouseWheel then
		
		local direction = math.sign(inputObject.Position.Z)
		local scaleVector = Vector2.one * ZoomAmount * direction
		local scale = UDim2.fromOffset(scaleVector.X, scaleVector.Y)
		local scaledSize = Frame.AbsoluteSize + scaleVector
		if scaledSize.X < MinimumSize.X or scaledSize.X > MaximumSize.X or scaledSize.Y < MinimumSize.Y or scaledSize.Y > MaximumSize.Y then return end

		local MousePos = Vector2.new(inputObject.Position.X, inputObject.Position.Y)
		
		-- Reposition with anchor point
		local currentAbsolutePosition = Frame.AbsolutePosition
		
		local FrameSize = Frame.AbsoluteSize
		local FramePos = Frame.AbsolutePosition
		local RelativePos = Vector2.new(math.clamp(MousePos.X-FramePos.X, 0, FrameSize.X), math.clamp(MousePos.Y-FramePos.Y, 0, FrameSize.Y))
		local ValuePos = RelativePos/FrameSize
		
		Frame.AnchorPoint = ValuePos
		local PositionDifference = currentAbsolutePosition - Frame.AbsolutePosition
		Frame.Position += UDim2.fromOffset(PositionDifference.X, PositionDifference.Y)
		
		Frame.Size += scale
	end
end)
UserInputService.InputBegan:Connect(function(inputObject)
	if inputObject.KeyCode == Enum.KeyCode.One then
		Frame.AnchorPoint = Vector2.one/2
		Frame.Position = UDim2.fromScale(0.5, 0.5)
		Frame.Size = UDim2.fromScale(0.8, 0.8)
	end
end)

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