Are you sure the position is changing in the video? It seems to stay the same, it’s just that the border moves.
It’s actually moving by roughly ~1 pixel, I know this because I was observing the absolute position in the explorer.
I am unsure to why it is important for your Ui to maintain the same position when adjusting the anchor point, but I am pretty sure that this is something you cannot change.
AnchorPoint changes the origin point of the Frame
0.5,0.5 means that the position you previously set it to is now the exact Center of your Frame.
By default (0,0) the position is TopLeft, so the Frame is actually “sticking out” 90 pixels to the right and 80 pixels below its position.
So if you want to change it to 0.5,0.5 and maintain your visual position, you need to add half the size of your Frame to the position. So position would be along the lines of:
UDim2.new(OldScaleX, OldOffsetX + 45, OldScaleY, OldOffsetY + 40)
Or since this is a script, here’s a calculated version of it that should work for your function there.
gui.Position = UDim2.fromOffset(oldAP.X + (gui.AbsoluteSize.X * desiredAnchorPoint.X), oldAP.Y + (gui.AbsoluteSize.Y * desiredAnchorPoint.Y))
Edited the function to make it so that it will work with any AnchorPoint now and now just /2 for 0.5,0.5
Edit: to clarify why your original function doesn’t work, AnchorPoint does NOT change the position of a GuiObject. It just changes where it’s rendered from. By default it renders the pixels of your GuiObject from the Top Left. In this case, the center is where it’s rendered from.
Your script seems to be pushing the gui left and up, I am not sure why.
I made one mistake of leaving desiredAnchorPoint.Y in the X side of the offset calculation, but besides from that, there should be no reason it’s doing that. What anchorpoint are you setting? 0.5,0.5?
Edit: Pushing it left should be happening, but pushing it up…? You make it sound like the Y is going down. Or is the frame itself moving down?
Since you hearted this it brought it back to my attention so I tested it.
The green part is where it was first.
It tweens to AnchorPoint 0.5,0.5 first,
then it tweens to the solution I gave you.
-- Same code for position, just changed it from TweenPosition
gui.Position = UDim2.fromOffset(oldAP.X + (gui.AbsoluteSize.X * desiredAnchorPoint.X), oldAP.Y + (gui.AbsoluteSize.Y * desiredAnchorPoint.Y))
For some reason when I change 0.5, 0.5
to 0.5, 0
, it moves the GUI to the left.
That GIF is a bit confusing since it’s too fast, but if you’re saying what I think you’re saying, you’re using the code I messed up a bit.
If I had to guess, the first parameter in UDim2.fromOffset is:
oldAP.X + (gui.AbsoluteSize.X * desiredAnchorPoint.Y)
and not
oldAP.X + (gui.AbsoluteSize.X * desiredAnchorPoint.X)
Like it should be.
Since with the proper parameters it works fine for me
I did use your function correctly, but it doesn’t work as intended. In the meantime someone figured out slightly different way to approach this problem and their solution works almost perfectly but there are few cases where it doesn’t work as well.
local originalPosition = frame.AbsolutePosition
local function setAnchorPoint(gui, desiredAnchor)
local anchorInfluence = desiredAnchor * gui.AbsoluteSize
gui.AnchorPoint = desiredAnchor
gui.Position = UDim2.fromOffset(anchorInfluence.X + originalPosition.X, anchorInfluence.Y + originalPosition.Y)
end
It involves saving the original position.
This function fails in these cases:
While it works in the following cases:
So you want there to be no minute “shift” in the UI as you move it around?
Yes, I want to have an option in my plugin that will keep the position of the anchor point as sometimes I have an GUI element perfectly positioned but with incorrect anchor point, and when I change the anchor point it’s really annoying to have to reposition the GUI element back to where it was.
Hmm… Alright let me see what I can do.
Are you okay with using Scale for position instead of offset?
Yes, the scale can be always converted back to offset if possible.
Here’s what I’ve whipped up, including my testing code. I found no issues with anything, nor any slight stammers in the Frame.
Edit: whoops?
local function SetAnchorPoint(Gui, DesiredAnchor)
local Canvas = Gui.Parent -- Object's Parent GUI (AbsoluteSize needed for Scaling.)
local ParentSize = Canvas.AbsoluteSize
local ChildSize = Gui.AbsoluteSize
local ChildPosition = Gui.AbsolutePosition
local CorrectionOffsetX = ChildSize.X * DesiredAnchor.X
local CorrectionOffsetY = ChildSize.Y * DesiredAnchor.Y
local CorrectedUDim2 = UDim2.fromScale((ChildPosition.X + CorrectionOffsetX) / ParentSize.X, (ChildPosition.Y + CorrectionOffsetY) / ParentSize.Y)
Gui.AnchorPoint = DesiredAnchor
Gui.Position = CorrectedUDim2
end
task.wait(5)
local Anchors = {
Vector2.new(0.5,0.5),
Vector2.new(1,1),
Vector2.new(0.5,0),
Vector2.new(0,0.5),
Vector2.new(1,0),
Vector2.new(0,1),
Vector2.new(1,0.5),
Vector2.new(0.5,1),
}
for _,V in pairs(Anchors) do
SetAnchorPoint(script.Parent.Frame, V)
task.wait(0.25)
end
It works perfectly, but it doesn’t seem to work when parented to another GUI element because it moves out far away.
Haahhh I’ll work on a fix really quick.
I’m such an idiot, must still be tired, the fix is so simple and might as well be done anyways when converting offsets to scaled values…
local function SetAnchorPoint(Gui, DesiredAnchor)
local Canvas = Gui.Parent -- Object's Parent GUI (AbsoluteSize needed for Scaling.)
local ParentSize = Canvas.AbsoluteSize
-- tada:
local ParentPosition = Canvas.AbsolutePosition
local ChildSize = Gui.AbsoluteSize
local ChildPosition = Gui.AbsolutePosition
-- tada:
ChildPosition = ChildPosition - ParentPosition
local CorrectionOffsetX = ChildSize.X * DesiredAnchor.X
local CorrectionOffsetY = ChildSize.Y * DesiredAnchor.Y
local CorrectedUDim2 = UDim2.fromScale((ChildPosition.X + CorrectionOffsetX) / ParentSize.X, (ChildPosition.Y + CorrectionOffsetY) / ParentSize.Y)
Gui.AnchorPoint = DesiredAnchor
Gui.Position = CorrectedUDim2
end
Here is my complete solution (which includes support for viewport when parent is not available).
--!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
local Map = {}
local function SetAnchorPoint(Gui, DesiredAnchor)
print("fired")
local Canvas = Gui.Parent -- Object's Parent GUI (AbsoluteSize needed for Scaling.)
local ParentSize = Canvas.AbsoluteSize
-- tada:
local ParentPosition = Canvas.AbsolutePosition
local ChildSize = Gui.AbsoluteSize
local ChildPosition = Gui.AbsolutePosition
-- tada:
ChildPosition = ChildPosition - ParentPosition
local CorrectionOffsetX = ChildSize.X * DesiredAnchor.X
local CorrectionOffsetY = ChildSize.Y * DesiredAnchor.Y
local CorrectedUDim2 = UDim2.fromScale((ChildPosition.X + CorrectionOffsetX) / ParentSize.X, (ChildPosition.Y + CorrectionOffsetY) / ParentSize.Y)
Gui.AnchorPoint = DesiredAnchor
Gui.Position = CorrectedUDim2
print(CorrectedUDim2)
end
function Map.MoveMouseAnchor(Map, Mouse)
local DesiredAnchr = Vector2.new(Mouse.X / 1000, Mouse.Y / 1000)
SetAnchorPoint(Map, DesiredAnchr)
end
return Map
I’m trying to achomplish a similar thing and move the anchorpoint to the mouse position. the GUI does not remain in its spot.