and I want to replicate this myself. but I ran into the problem that I don’t know how to implement such a thing so that the elements it scrolls are positioned on a circle, and that it is not exactly like ScrollingFrame but bound to each frame and when the player spins the wheel down, the whole canvas shifts exactly on one frame and not on another value.
In addition, I also need to consider that elements that are farther from the center (of the selected element) should be rotated to the right side and change their transparency.
Any advice would be welcomed. i’m not asking you to write a ready-made script, just help figure out how to do it, but would appreciate it if someone would go to such lengths :3
I think you want to use the UI Page layout, that is what it seems to be, it has all of the options that are required in the video, try testing it out and see if its right!
ok, but that’s not exactly what I had in mind. it has similar parameters, but it can only move vertically and horizontally. and I need it to move along the border of a circle. and this circle itself has a 1/4th of a fraction, which is visible on the screen if you mentally draw a line, along the centers of the frames he moves with the mouse wheel.
I see, maybe this could be scripting, the animations seem pretty advanced for a UI, you probably will have to script it in some way, using tweening, and more.
I know it should be used, but I would like at least some tiny tips on how to implement positioning of UI elements on a circle, but not just positioning, but also their dynamic change of position on demand (event).
local y = 30
print(math.sin(y)) -- that will give you the value for the y and just do the same for the x and you should be able to get the circle motion you wanted
Hey, I remember seeing this post and was bored so I made it. You’d need to set up your own input controlling and such but I think you needed help with the math, it was surprisingly relatively simple.
local tweenService = game:GetService('TweenService')
local container = script.Parent
local slots = {}
local TOTAL_SPAN_DEGREES = 90
local DURATION = 0.25
local EASING_STYLE = Enum.EasingStyle.Sine
local EASING_DIRECTION = Enum.EasingDirection.InOut
local MIN_SIZE = UDim2.fromOffset(25, 25)
local MAX_SIZE = UDim2.fromOffset(50, 50)
local FRAME_COUNT = 8
local currentFocus = 0
local currentFocusIndex = 0
local totalSpanRads = math.rad(TOTAL_SPAN_DEGREES)
for i = 1, FRAME_COUNT do
local frame = Instance.new('Frame')
frame.Size = UDim2.new(0, 10, 0, 10)
frame.AnchorPoint = Vector2.one * 0.5
frame.Parent = script.Parent
slots[i] = frame
end
local function lerp(a, b, t)
return a + (b - a) * t
end
local function getValue(value, style, direction)
return tweenService:GetValue(value, style, direction)
end
local last
local function focus(targetIndex: number) -- this does the actual interpolation and such, call this to actually scroll it to the targetIndex
local fixedValue = math.clamp(targetIndex, 1, FRAME_COUNT) -- clamp it so we don't exceed the number of frames
if currentFocusIndex == fixedValue then -- same value as before so we don't wanna do anything
return
end
currentFocusIndex = fixedValue
targetIndex = fixedValue
local now = os.clock()
last = now
local valueNow = currentFocus
repeat
task.wait()
local targetIndex = lerp(valueNow, targetIndex, getValue(math.min((os.clock() - now) / DURATION, 1), EASING_STYLE, EASING_DIRECTION))
currentFocus = targetIndex
for index, slot in slots do
local diff = targetIndex - index -- difference between this index and the target index which is used to determine at what angle to position the frames
local angle = diff / FRAME_COUNT * totalSpanRads - (math.pi * 0.75) -- angle of the position from the origin of the frame; subtract 0.75 * pi because we are using the top-left corner as the "target" corner
slot.Transparency = math.clamp(math.abs(diff * 0.5), 0, 1) -- set the transparency to be 0 when this is the current focus, and to 0.5 when it's the next focus and 1 when it's not the next focus
slot.Size = MAX_SIZE:Lerp(MIN_SIZE, getValue(math.clamp(math.abs(diff) + 0.5, 0, 1), EASING_STYLE, EASING_DIRECTION)) -- same as above but for size
slot.ZIndex = -math.abs(diff) -- set the z index so the current focus is on top of the previous and next focus
slot.Rotation = diff * 22.5
local x = math.cos(angle) * 100 -- x position at the angle
local y = math.sin(angle) * 100 -- y position at the angle
slot.Position = UDim2.fromOffset(x + 0.5 * container.AbsoluteSize.X, y + 0.5 * container.AbsoluteSize.Y) -- finally set the position
end
until os.clock() - now > DURATION or last ~= now
end
script.Parent.InputChanged:Connect(function(input) -- basic input thing, you can implement your controls however you want
if input.UserInputType ~= Enum.UserInputType.MouseWheel then
return
end
focus(currentFocusIndex + math.sign(input.Position.Z))
end)
focus(1)