This module is no longer needed.
In Update 421, Roblox added smooth scrolling to ScrollingFrames.
We had a good long run here, and I know this module helped a lot of people while it was around. I hope you all benefited from it, and I’m glad to see Roblox improving the platform so modules like these are unnecessary!
I’m certain that one day, Roblox will make this behavior the default. Until that day, this is what I’ll be using!
^ Just saying, I called it.
I’m leaving the post below for documentation + posterity. Besides, we might find some use for it again in the future, who knows.
I’ll start with this note:
It is tied to framerate, so it’ll scroll smoothly regardless of FPS. I view this as a feature, but it’s worth noting that slower devices will scroll slower.
The issue:
ScrollingFrames on PC are painful to use. Scrolling on them jumps the CanvasPosition around, and they have no inertia at all.
If there’s text in a ScrollingFrame, it’s hard to read because when you scroll it jumps and you lose your place. My game (Lua Learning) is a lot of reading, so being able to scroll without losing track is a big deal. This module is designed for my case, but I’m sure many of you could use it as well.
(These GIFs are 25FPS, but the smooth version is juicy in game at 60FPS.)
Default:
SmoothScroll:
The Solution:
I’ve seen a couple weird ways people have done it, none of them easy to just plug into your game.
One way was made out of multiple frames and required you to completely change your code, others are hard coded to a single frame, etc.
So, I wrote another open-source module!
Implementation and usage is incredibly easy. You use regular ScrollingFrames when creating your GUIs, and just tell the module to make it smooth. It does the rest!
The API:
(I used Rodocs to document the module, and I highly recommend it.)
function SmoothScroll.Enable(Frame, Sensitivity, Friction, Inverted, Axis)
Sets a ScrollingFrame to scroll smoothly
Parameters:
-
Frame
[ScrollingFrame]
The ScrollingFrame object to apply smoothing to -
Sensitivity
[Optional Number]
How many pixels it scrolls per wheel turn -
Friction
[Optional Number]
What the velocity is multiplied by each frame (Clamped between 0.2 and 0.99) -
Inverted
[Optional Bool]
Inverts the scrolling direction -
Axis
[Optional String]
“X” or “Y”. If left out, will default to whichever Axis is scrollable or “Y” if both are valid
Returns:
nil
function SmoothScroll.Disable(Frame)
Sets a ScrollingFrame to scroll normally
Parameters:
-
Frame
[ScrollingFrame]
The ScrollingFrame object to remove smoothing from
Returns:
nil
Example usage:
It’s super simple to use. It’s also coded defensively, so even if you mess up, it’ll either use default or just ‘warn’ and not smooth it. This means the module should never halt or break your code. If you find an error case that does, let me know!
Simple use example
local SmoothScroll = require(script.SmoothScroll)
local ScreenGui = game.Players.LocalPlayer:WaitForChild("PlayerGui"):WaitForChild("ScreenGui")
SmoothScroll.Enable(ScreenGui.ScrollingFrame)
This example automatically smooths any ScrollingFrame in your game except ones that you tag with "DontSmooth" via ColectionService. This code is currently running in Lua Learning! It's super useful.
local CollectionService = game:GetService("CollectionService")
local Player = game.Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")
local SmoothScroll = require(script.SmoothScroll)
local Smoothed = {}
local function DescendantAdded(Descendant)
if Descendant:IsA("ScrollingFrame") and not Smoothed[Descendant] and not CollectionService:HasTag(Descendant, "DontSmooth") then
SmoothScroll.Enable(Descendant)
Smoothed[Descendant] = true
end
end
local function DescendantRemoving(Descendant)
if Descendant:IsA("ScrollingFrame") and Smoothed[Descendant] then
SmoothScroll.Disable(Descendant)
Smoothed[Descendant] = nil
end
end
-- Initialize
for _, Descendant in pairs(PlayerGui:GetDescendants()) do
DescendantAdded(Descendant)
end
PlayerGui.DescendantAdded:Connect(DescendantAdded)
PlayerGui.DescendantRemoving:Connect(DescendantRemoving)
Module:
Repository:
Conclusion:
I hope you guys find this as useful as I do! I’m certain that one day, Roblox will make this behavior the default. Until that day, this is what I’ll be using! I hope they also let us disable/alter the sensitivity and friction of the mobile ScrollingFrames.