Moving a GUI anchor point

Howdy. My goal is to shrink a frame towards the mouse. My idea was if I could position the anchor point to where the mouse first clicked, the frame should resize naturally based off that position.

We don’t HAVE to move the anchor point if someone has a different solution. Either way I’m clueless on how to achieve this.

local textButton = script.Parent

function mouseButton1Down()
	warn('button was clicked, move anchor point to position')
end

textButton.MouseButton1Down:Connect(mouseButton1Down)
local mouse = game.Players.LocalPlayer:GetMouse()

print(mouse.X)
print(mouse.Y)

mouse.x and mouse.y get the mouse position

Use those values to set the anchor point.

Those values would be crazy numbers depending on where my mouse is.

local textButton = script.Parent

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

function mouseButton1Down()
	warn(mouse.x,mouse.y)
end

textButton.MouseButton1Down:Connect(mouseButton1Down)

I definitely don’t want to set the anchor point to those positions. Thank you though!

Thats because its counting pixels using offset and not scale.

You can convert those values to UiScale which is what roblox uses for AnchorPoint.
Follow this: How can you convert offset size to scale size? - #7 by kylerzong

I clicked on the button near the anchor point of the button (default top left), and it gave me a similar position.

If you are using scale instead of offset, then yeah these would seem like crazy numbers. However it returns pixels which is what offset uses. But if you would rather use scale, you can convert them to scale values using what @lrd14 said.

1 Like

You can get the desired anchor point value by that:

local textButton = script.Parent
local player = ...

local function mouseButton1Down()
	local mouse = player:GetMouse()
	local mouse_position = Vector2.new(mouse.X, mouse.Y)
	local anchor_point = (mouse_position - textButton.AbsolutePosition) / textButton.AbsoluteSize
	textButton.AnchorPoint = anchor_point
end

textButton.MouseButton1Down:Connect(mouseButton1Down)
1 Like

Thank you! This is exactly what I was looking for!

This is an unexpected outcome that I wish to resolve… How can I keep the TextButton position locked into what it was before changing the anchor point. I have to offset the position based off the “anchor_point”?

Do you mean the last position it was? Can you explain more?

1 Like

Don’t worry about it boss! I found what I was looking for in another post. Thank you for the help!

--!strict

local Workspace = game:GetService("Workspace")

local Util = {}

-- PS stands for position and size
function Util.GetParentPS(gui: GuiObject): (Vector2, Vector2)
	local parent = gui.Parent
	if parent then
		if parent:IsA("GuiObject") then
			return parent.AbsolutePosition, parent.AbsoluteSize
		end
	end
	return Vector2.zero, Workspace.Camera.ViewportSize
end

function Util.SetAnchorPointWithoutMoving(gui: GuiObject, desiredPoint: Vector2)
	local parentPosition, parentSize = Util.GetParentPS(gui)
	
	local childSize = gui.AbsoluteSize
	local childPosition = gui.AbsolutePosition
	
	-- Calculate the relative position
	childPosition = childPosition - parentPosition

	local correctionOffsetX = childSize.X * desiredPoint.X
	local correctionOffsetY = childSize.Y * desiredPoint.Y

	local correctedPosition = UDim2.fromScale(
		(childPosition.X + correctionOffsetX) / parentSize.X,
		(childPosition.Y + correctionOffsetY) / parentSize.Y
	)
	
	gui.AnchorPoint = desiredPoint
	gui.Position = correctedPosition
end

return Util
2 Likes

I can’t believe that got dug up again, enjoy the fix. :joy:
If you need any more help on other GUI issues feel free to ask me, I should have some knowledge of it.

1 Like

Maybe you know the cause of this issue?

I’m using a GUI dragging module with your anchor point function. When I click the bottom half AND ONLY the bottom half, it does that weird offset. When I remove the anchor aspect of the script I no longer have the issue when clicking the bottom half.

Sorry this is a lot of code to look at! Just lemme know if anything comes to mind. Thank you.

--[[
	@Author: Spynaz
	@Description: Enables dragging on GuiObjects. Supports both mouse and touch.
	
	For instructions on how to use this module, go to this link:
	https://devforum.roblox.com/t/simple-module-for-creating-draggable-gui-elements/230678
--]]

local UDim2_new = UDim2.new

local UIScaleObject = script.UIScaleObject.Value

local UserInputService = game:GetService("UserInputService")

local DraggableObject 		= {}
DraggableObject.__index 	= DraggableObject

-- Sets up a new draggable object
function DraggableObject.new(Object)
	local self 			= {}
	self.Object			= Object
	self.DragStarted	= nil
	self.DragEnded		= nil
	self.Dragged		= nil
	self.Dragging		= false

	setmetatable(self, DraggableObject)

	return self
end

function DraggableObject:ZIndexOverlap(index)
	local frame = self.Object
	
	for a,child in frame:GetDescendants() do
		if child:IsA('GuiBase') then
			child.ZIndex += index
		end
	end	

	frame.ZIndex += index
end

function SetAnchorPoint(frame,position)
	local mouse_position = Vector2.new(position.X,position.Y)
	local anchor_point = (mouse_position - frame.AbsolutePosition) / frame.AbsoluteSize
	
	local Canvas = frame.Parent
	local ParentSize = Canvas.AbsoluteSize

	local ParentPosition = Canvas.AbsolutePosition
	local ChildSize = frame.AbsoluteSize
	local ChildPosition = frame.AbsolutePosition

	ChildPosition = ChildPosition - ParentPosition

	local CorrectionOffsetX = ChildSize.X * anchor_point.X
	local CorrectionOffsetY = ChildSize.Y * anchor_point.Y

	local CorrectedUDim2 = UDim2.fromScale((ChildPosition.X + CorrectionOffsetX) / ParentSize.X, (ChildPosition.Y + CorrectionOffsetY) / ParentSize.Y)
	frame.AnchorPoint = anchor_point
	frame.Position = CorrectedUDim2
end

-- Enables dragging
function DraggableObject:Enable()
	local object			= self.Object
	local dragInput			= nil
	local dragStart			= nil
	local startPos			= nil
	local preparingToDrag	= false

	-- Updates the element
	local function update(input)
		local delta 		= (input.Position - dragStart)/UIScaleObject.Scale
		
		local newPosition	= UDim2_new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
		object.Position 	= newPosition

		return newPosition
	end

	self.InputBegan = object.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			SetAnchorPoint(object,UserInputService:GetMouseLocation()) --SETTING THE ANCHOR POINT HERE
			
			preparingToDrag = true
			
			self:ZIndexOverlap(10)


			local connection 
			connection = input.Changed:Connect(function()
				if input.UserInputState == Enum.UserInputState.End and (self.Dragging or preparingToDrag) then
					
					self.Dragging = false
					connection:Disconnect()

					if self.DragEnded and not preparingToDrag then
						self.DragEnded()
					end

					self:ZIndexOverlap(-10)

					preparingToDrag = false
				end
			end)
		end
	end)

	self.InputChanged = object.InputChanged:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
			dragInput = input
		end
	end)

	self.InputChanged2 = UserInputService.InputChanged:Connect(function(input)
		if object.Parent == nil then
			self:Disable()
			return
		end

		if preparingToDrag then
			preparingToDrag = false

			if self.DragStarted then
				self.DragStarted()
			end

			self.Dragging	= true
			dragStart 		= input.Position
			startPos 		= object.Position
		end

		if input == dragInput and self.Dragging then
			local newPosition = update(input)

			if self.Dragged then
				self.Dragged(newPosition)
			end
		end
	end)
end

-- Disables dragging
function DraggableObject:Disable()
	self.InputBegan:Disconnect()
	self.InputChanged:Disconnect()
	self.InputChanged2:Disconnect()

	if self.Dragging then
		self.Dragging = false

		if self.DragEnded then
			self.DragEnded()
		end
	end
end

return DraggableObject

Found this issue. I needed to subtract the “GuiInset” from the mouse Y position.

local guiInset = game:GetService('GuiService'):GetGuiInset()

local function SetAnchorPoint(Gui, mouse)
	local mouse_position = Vector2.new(mouse.X, mouse.Y-guiInset.Y)

My bad; I was busy with family matters for a couple of days, but yeah that was all I could figure would be the issue.

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