Scrolling by pressing a button for the shop UI

I’ve written a script to allow users to scroll to their desired positions by pressing a button, but I’m not sure if there’s an easier way because when I add something new to the shop, I have to rewrite the positions.

Can you help me find an easier way?

function hareketettir(pos)
	local Oran = list.AbsoluteCanvasSize.X/6543.354

	local tween = TweenService:Create(list,TweenInfo.new(1,Enum.EasingStyle.Exponential,Enum.EasingDirection.Out),{CanvasPosition = Vector2.new(Oran*pos+1,0)})
	tween:Play()
end

function sagbutonekle(v)
	spawn(function()
		local frame = list:WaitForChild(v.Name,1)
		if frame then
			local pos = frame:GetAttribute("pos")
			v.frame.MouseButton1Click:Connect(function()
				hareketettir(pos)
			end)
			
			local tweeninfo = TweenInfo.new(.25,Enum.EasingStyle.Quart)
			local entertween = TweenService:Create(v.frame,tweeninfo,{Size = UDim2.new(1.1,0,1.1,0)})
			local entertween2 = TweenService:Create(v.frame.ImageLabel,tweeninfo,{Rotation = 20})
			local leavetween = TweenService:Create(v.frame,tweeninfo,{Size = UDim2.new(1,0,1,0)})
			local leavetween2 = TweenService:Create(v.frame.ImageLabel,tweeninfo,{Rotation = 0})
			
			v.frame.MouseEnter:Connect(function()
				entertween:Play()
				entertween2:Play()
			end)
			
			v.frame.MouseLeave:Connect(function()
				leavetween:Play()
				leavetween2:Play()
			end)
		end
	end)
end

1 Like

I don’t quite understand the code, I think it’s written in a different language but from what I understood, here’s a better method. Each button should have a known frame to go to, when the button is clicked, animate CanvasPosition to the AbsolutePosition of that frame. You can keep your system the same but instead of adding the attributes manually make it a loop at the start of the code so the attributes are set at runtime, set the attribute to the AbsolutePosition of the frame that you need to go to, you don’t need to do the calculation of Oran (whatever that means) if you use my method btw.

One way to make your code more maintainable and adaptable is to dynamically calculate the positions based on the number of items in your shop.

So Using the pos variable is calculated based on the LayoutOrder of each item in the shop. This way, you don’t need to hardcode positions, and the script will adapt automatically when you add or remove items from the shop.

function hareketettir(pos)
    local Oran = list.AbsoluteCanvasSize.X / 6543.354

    local tween = TweenService:Create(list, TweenInfo.new(1, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out), { CanvasPosition = Vector2.new(Oran * pos + 1, 0) })
    tween:Play()
end

function sagbutonekle(v)
    spawn(function()
        local frame = list:WaitForChild(v.Name, 1)
        if frame then
            local itemCount = #list:GetChildren() -- count the number of items in the shop
            local pos = itemCount - v.LayoutOrder -- calculate the position dynamically
            v.frame.MouseButton1Click:Connect(function()
                hareketettir(pos)
            end)

            local tweeninfo = TweenInfo.new(.25, Enum.EasingStyle.Quart)
            local entertween = TweenService:Create(v.frame, tweeninfo, { Size = UDim2.new(1.1, 0, 1.1, 0) })
            local entertween2 = TweenService:Create(v.frame.ImageLabel, tweeninfo, { Rotation = 20 })
            local leavetween = TweenService:Create(v.frame, tweeninfo, { Size = UDim2.new(1, 0, 1, 0) })
            local leavetween2 = TweenService:Create(v.frame.ImageLabel, tweeninfo, { Rotation = 0 })

            v.frame.MouseEnter:Connect(function()
                entertween:Play()
                entertween2:Play()
            end)

            v.frame.MouseLeave:Connect(function()
                leavetween:Play()
                leavetween2:Play()
            end)
        end
    end)
end

I apologize for not providing enough detail.

The values with the ‘Pos’ attribute are the positions on a canvas with a resolution of 1920x1080. For example


image

hareketettir = A function to bring it to the desired position.
Oran = The value that scales the positions entered at 1920x1080 resolution according to the changing resolution.

Alright, did you try my method?

1 Like

I didn’t fully understand the method, are you telling me to increment the canvas position until it reaches the correct position?

No no, basically, store the name of the frame as the attribute, ex. button 1 has a string attribute named “Frame” with a value of “Frame1” and button 2 has the value as “Frame2”. In your code, do this

for i, v in ipairs(buttons) do
	local frameName = v:GetAttribute("Frame")
	local frame: Frame = holder:FindFirstChild(frameName)
	if not frame then warn(`Frame {frameName} not found.`) continue end -- In case you wrote a wrong name.

	setCanvasPosition(frame.AbsolutePosition)
end
1 Like

AbsolutePosition provides the on-screen position of the frame. So, if I adjust the canvas position based on AbsolutePosition, it will end up in the wrong position. If I previously store all AbsolutePositions in a specific table and execute them, it will probably work correctly at first. However, it will bring items to the wrong positions when the screen size changes.

No, it will never work wrong, I just forgot to say that you need to do frame.AbsolutePosition - scrollingFrame.AbsolutePosition and set the CanvasPosition to it and it will work independent of the screen size, that all needs to be done in runtime.

1 Like

You’ve made much more sense now; thank you.

The final version of the code might be useful for someone.

function MoveCanvas(frame)
	local X = list.CanvasPosition.X+frame.AbsolutePosition.X-list.AbsolutePosition.X

	local tween = TweenService:Create(list,TweenInfo.new(1,Enum.EasingStyle.Exponential,Enum.EasingDirection.Out),{CanvasPosition = Vector2.new(X,0)})
	tween:Play()
end

Your welcome.


I don’t think you need this part though.

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