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:
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:
You did awesome thatās spot on. Thank you, any problems Iāll let you know
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)
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
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
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.