I released a plugin a few days ago, but am wanting to add in a slider.
I saw that buildthomas created a Rain Plugin, and it had sliders. I did some research and found that Roblox doesn’t have any simple way to do this (correct me if I’m wrong)
I was hoping that someone might have some knowledge to help me out.
I believe @buildthomas’s rain plugin uses this Studio Widgets library to give his plugin the feel that it does. You can always look at the rain plugin it’s self by inserting it via InsertService after installing it (or looking in your Roblox plugins directory).
I literally had a video tutorial planned for doing this. There’s a lot of “gotchas” when making sliders, and making them user-friendly.
Some tips:
Use an overlaying transparent button to “capture” initial clicks. It should be slightly larger than the slider on both axes. Capture clicks using the MouseButton1Down event.
Use UserInputService.InputChanged to detect mouse movement when the user is clicking
Use UserInputService.InputEnded to check if the user stopped clicking
The reason you want to use UserInputService is because the user might drag the mouse “out of bounds” of the slider frame, and thus the slider mouse events won’t be registering.
While this misses the context of the actual UI frame being used, here’s the code I have for my slider in a game I’m working on currently:
-- Slider
-- Crazyman32
-- August 11, 2018
--[[
slider = Slider.new(frame)
slider.Frame
slider.Value
slider:SetValue(value)
slider.Changed(value)
slider.Released(value)
--]]
local Slider = {}
Slider.__index = Slider
local userInput = game:GetService("UserInputService")
local INCREMENT_SNAP = 0.125
local INCREMENT_SNAP_THRESHOLD = 0.01
local function Round(x, mult)
return math.floor((x / mult) + 0.5) * mult
end
function Slider.new(frame, initial)
local self = setmetatable({
Frame = frame;
Value = initial;
}, Slider)
self._slider = frame:WaitForChild("Slider")
self._bar = self._slider:WaitForChild("Bar")
self._line = self._bar:WaitForChild("Line")
local capture = self._slider:WaitForChild("Capture")
self._changed = Instance.new("BindableEvent")
self.Changed = self._changed.Event
self._released = Instance.new("BindableEvent")
self.Released = self._released.Event
local dragging = false
capture.MouseButton1Down:Connect(function(x, y)
dragging = true
self:Calculate(x)
end)
userInput.InputChanged:Connect(function(input, processed)
if (dragging and input.UserInputType == Enum.UserInputType.MouseMovement) then
self:Calculate(input.Position.X)
end
end)
userInput.InputEnded:Connect(function(input, processed)
if (dragging and input.UserInputType == Enum.UserInputType.MouseButton1) then
dragging = false
self._released:Fire(self.Value)
end
end)
self:SetValue(initial or 0)
return self
end
function Slider:SetValue(value)
value = math.clamp(value, 0, 1)
self._bar.Size = UDim2.new(value, 0, 1, 0)
self._line.AnchorPoint = Vector2.new(value, 0.5)
self.Value = value
end
function Slider:Calculate(mouseX)
local ratio = math.clamp(((mouseX - self._slider.AbsolutePosition.X) / self._slider.AbsoluteSize.X), 0, 1)
local ratioRounded = Round(ratio, INCREMENT_SNAP)
if (math.abs(ratio - ratioRounded) < INCREMENT_SNAP_THRESHOLD) then
ratio = ratioRounded
end
self:SetValue(ratio)
self._changed:Fire(ratio)
end
return Slider