UI tween zoom in

Hey, I was wondering on how I could make the first frame of my UI start out by going small and zooming up in scale?

I would advise against using :TweenSize, :TweenSizeAndPosition, and :TweenPosition as TweenService is much more reliable, and you donā€™t have to bother inputting the OverrideTween argument as it does it automatically (basically handles spamming without the need of a debounce).

Anyway, hereā€™s how Iā€™d approach it:

local tweenService = game:GetService('TweenService')

local isOpen = false

local tweenInfo = TweenInfo.new(0.5)
local closeTween = tweenService:Create(script.Parent:WaitForChild('Frame'), tweenInfo, {Size = UDim2.new(0,0,0,0)})
local openTween = tweenService:Create(script.Parent:WaitForChild('Frame'), tweenInfo, {Size = UDim2.new(0.5,0,0.5,0)})

script.Parent:WaitForChild('ToggleButton').MouseButton1Click:Connect(function()
	isOpen = not isOpen --[[this turns a boolean from true/truthy to false, or false/falsy to true
	// truthy is considered not nil and not false
	// false/falsy (falsy is considered nil and false) to true ]]
	if isOpen then -- if it's to be opened then,
		openTween:Play()
	else -- otherwise it's false
		closeTween:Play()
	end
end)

-----

--// or if you don't want the if statement, you could use ternary operators like this, 
--// although I don't recommend it if you don't know how ternary operators work in Lua:

script.Parent:WaitForChild('ToggleButton').MouseButton1Click:Connect(function()
	isOpen = not isOpen
	local selectedTween = isOpen and openTween or closeTween
	selectedTween:Play()
end)

Hereā€™s my setup, also itā€™s important to make the frameā€™s AnchorPoint at 0.5,0.5 and its position at 0.5,0,0.5,0 if you want it to always be at the centre of your screen:
Screen Shot 2021-10-27 at 10.07.44 PM

5 Likes

Wow thatā€™s amazing thanks. If I had multiple frames like 3, how would I q the other ones to start playing right after? (They donā€™t have to zoom in).

Like one after another, or are those other frames children of a ā€œmasterā€ frame?

If the frames are a child of a single frame, it should scale up automatically.

If the former, one after another, it is a bit more complicated, we have to factor in whether there was another click, you could do this manually or with loops, I recommend doing it with loops and tables as it greatly reduces the amount of redundancy and repetition in the code:

Code:

local tweenService = game:GetService('TweenService')

local frames = {
	script.Parent:WaitForChild('Frame1');
	script.Parent:WaitForChild('Frame2');
	script.Parent:WaitForChild('Frame3')
}

local tweens = {}

local tweenInfo = TweenInfo.new(0.5)

for i,v in ipairs(frames) do -- this loop creates tweens to open and close each frame
	tweens[v] = {
		['Open'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,100,0,100)});
		['Close'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,0,0,0)});
	}
end

local open = false

script.Parent.Parent:WaitForChild('TextButton').MouseButton1Click:Connect(function()
	open = not open
	local tempIsOpen = open -- this sort of "reserves" the state that the frame was if we click it a second or third time
	for i,v in ipairs(frames) do -- let's use ipairs as it's a bit faster than pairs and it ensures everything is done in order
		if tempIsOpen ~= open then -- this essentially signifies that the button was clicked again after our initial click
			return
		end
		local chosenTween = tweens[v][open and 'Open' or 'Close'] -- essentially the same as the ternary example I gave you earlier but it could be made easier to understand with an if-statement
		chosenTween:Play()
		task.wait(0.1) -- wait 0.1 seconds before the next anim plays
	end
end)

Setup:

Screen Shot 2021-10-27 at 10.25.06 PM

You did awesome thatā€™s spot on. Thank you, any problems Iā€™ll let you know

1 Like

I have it all working execpt for the size, it all goes to a single size not spread apart. hereā€™s an example: https://gyazo.com/12d2c57dbf9024cd126b19894acd8864

Ah I see, I think you might be using offset to size your children frames, itā€™s generally seen as good practice to use scale. So instead of sizing your frames like 0, 100, 0, 500, and using the second and fourth arguments, use the first and third arguments, something like this: 0.5, 0, 0.5, 0. To maintain a constant aspect ratio, use a UIAspectRatioConstraint, and you can further constrain the size with a UISizeConstraint.

Also you might want to enable TextScaled on your text labels.

Textscaled is on, and I used UIAspectRatioConstraint and more. But the frames all go to one size. I think it may be because of this

for i,v in ipairs(frames) do -- this loop creates tweens to open and close each frame
	tweens[v] = {
		['Open'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,100,0,100)});
		['Close'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,0,0,0)});

Yeah, you should be using Scale for that, I was making the assumption that all of your frames were the same size. You can do something like this:

tweens = {
    [frame1] = {
        ['Open'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0.5,0,0.5,0)});
        ['Close'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,0,0,0)});
    };
    [frame2 --[[ensure you're referencing the actual frame inside of the brackets, it should be an instance, not a string]]] = {
        ['Open'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0.5,0,0.1,0)});
        ['Close'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,0,0,0)});
    };
}

You could also probably use attributes instead of manually defining each of the frames.

Alright sorry im kinda rusty, but some of it works. No matter what I do, only the first [frame1] works. The thing is frame 1 is local frame1 = script.Parent.Top, but its controlling something else. Ill provide my code, images of UI, and a GIF.

local tweenService = game:GetService('TweenService')

local frame1 = script.Parent.Top
local frame2 = script.Parent.Backgroundscroll.ScrollingFrame.Person1


local frames = {
	script.Parent:WaitForChild('Top');
	script.Parent:WaitForChild('Backgroundscroll');
	script.Parent.Backgroundscroll.ScrollingFrame:WaitForChild('Person1')
}

local tweens = {}

local tweenInfo = TweenInfo.new(0.7)

for i,v in ipairs(frames) do -- this loop creates tweens to open and close each frame
	tweens = {
		[frame1] = {
			['Open'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0.944, 0,0.266, 0)});
			['Close'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,0,0,0)});
		};
		[frame2 --[[ensure you're referencing the actual frame inside of the brackets, it should be an instance, not a string]]] = {
			['Open'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0.944, 0,0.266, 0)});
			['Close'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,0,0,0)});
		};
	}
end

local open = false

script.Parent.Parent:WaitForChild('Open').MouseButton1Click:Connect(function()
	open = not open
	local tempIsOpen = open -- this sort of "reserves" the state that the frame was if we click it a second or third time
	for i,v in ipairs(frames) do -- let's use ipairs as it's a bit faster than pairs and it ensures everything is done in order
		if tempIsOpen ~= open then -- this essentially signifies that the button was clicked again after our initial click
			return
		end
		local chosenTween = tweens[v][open and 'Open' or 'Close'] -- essentially the same as the ternary example I gave you earlier but it could be made easier to understand with an if-statement
		chosenTween:Play()
		task.wait(0.1) -- wait 0.1 seconds before the next anim plays
	end
end)

image
https://gyazo.com/3ec6cd1c1f77d4f46b0bbf69a84af963

I forgot to check errors, it says this
22:25:33.087 Players.jackthehunter25.PlayerGui.KickUI.Frame.LocalScript:39: attempt to index nil with ā€˜Openā€™ - Client - LocalScript:39 line 39 is

local chosenTween = tweens[v][open and 'Open' or 'Close']

Sorry, I was away for a few mins. Try something like this:

local frame1 = script.Parent.Top
local frame2 = script.Parent.Backgroundscroll -- I think you'd only need these 2

tweens = {
		[frame1] = {
			['Open'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0.944, 0,0.266, 0)});
			['Close'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,0,0,0)});
		};
		[frame2] = {
			['Open'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0.944, 0,0.266, 0)});
			['Close'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,0,0,0)});
		};
	};
};
local open = false
script.Parent.Parent:WaitForChild('Open').MouseButton1Click:Connect(function()
    -- continue the rest of the script here, don't wanna flood the thread

It should address the error you mentioned as well as there was a third frame that was in the frames table but wasnā€™t in the tweens table.

Sorry for the late response, Players.jackthehunter25.PlayerGui.KickUI.Frame.LocalScript:38: attempt to index nil with ā€˜Closeā€™

Can you send your updated script?

local tweenService = game:GetService('TweenService')


local frames = {
	script.Parent:WaitForChild('Top');
	script.Parent:WaitForChild('Backgroundscroll');
	script.Parent.Backgroundscroll.ScrollingFrame:WaitForChild('Person1')
}

local tweens = {}

local tweenInfo = TweenInfo.new(0.7)

local frame1 = script.Parent.Top
local frame2 = script.Parent.Backgroundscroll

for i,v in ipairs(frames) do -- this loop creates tweens to open and close each frame
	tweens = {
		[frame1] = {
			['Open'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0.944, 0,0.266, 0)});
			['Close'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,0,0,0)});
		};
		[frame2] = {
			['Open'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0.944, 0,0.266, 0)});
			['Close'] = tweenService:Create(v, tweenInfo, {Size = UDim2.new(0,0,0,0)});
		};
	};
end

local open = false
script.Parent.Parent:WaitForChild('Open').MouseButton1Click:Connect(function()
	open = not open
	local tempIsOpen = open -- this sort of "reserves" the state that the frame was if we click it a second or third time
	for i,v in ipairs(frames) do -- let's use ipairs as it's a bit faster than pairs and it ensures everything is done in order
		if tempIsOpen ~= open then -- this essentially signifies that the button was clicked again after our initial click
			return
		end
		local chosenTween = tweens[v][open and 'Open' or 'Close'] -- essentially the same as the ternary example I gave you earlier but it could be made easier to understand with an if-statement
		chosenTween:Play()
		task.wait(0.1) -- wait 0.1 seconds before the next anim plays
	end
end)

I see, try removing this line:

script.Parent.Backgroundscroll.ScrollingFrame:WaitForChild('Person1')

Also remove this loop:

for i,v in ipairs(frames) do -- this loop creates tweens to open and close each frame

v is underlined red

tweenService:Create(v,

Oh I see, switch out each v for their respective frame:

        [frame1] = {
			['Open'] = tweenService:Create(frame1
            -- same with close, and same with the other frame
1 Like

after some small fixes i got it. some issues tho. how do I make it so that it doesnt zoom from a random place, (want it to start in middle), and is always closed at first and never visable. sorry if this is a lot, i never expected it to be this much :laughing:
https://gyazo.com/f30263b24130877e8f7e415c7fbf33a9

will send updated code if needed

I see, youā€™d probably want to play around with the AnchorPoint properties. My guess is that the top portionā€™s AnchorPoint would be 0.5,1, and the bottom portionā€™s AnchorPoint would be 0.5,0.

As for having it closed by default, just make the framesā€™ sizes 0,0,0,0.