Skip to content

Instantly share code, notes, and snippets.

@Meorawr
Last active August 2, 2023 22:28
Show Gist options
  • Save Meorawr/d47e94203a15c071a31b5ce798943c00 to your computer and use it in GitHub Desktop.
Save Meorawr/d47e94203a15c071a31b5ce798943c00 to your computer and use it in GitHub Desktop.
Bidirectional Scroll Frame
local ScrollChild = CreateFrame("Frame")
ScrollChild:SetSize(750, 750)
local ScrollChildTexture = ScrollChild:CreateTexture()
ScrollChildTexture:SetPoint("CENTER")
ScrollChildTexture:SetTexture([[Interface\ICONS\TEMP]])
local ScrollFrame = CreateFrame("ScrollFrame")
ScrollFrame:SetPoint("CENTER")
ScrollFrame:SetSize(500, 500)
ScrollFrame:SetScrollChild(ScrollChild)
ScrollFrame.GetHorizontalPanExtent = function(self)
return self.horizontalPanExtent
end
ScrollFrame.SetHorizontalPanExtent = function(self, panExtent)
self.horizontalPanExtent = panExtent
end
ScrollFrame.GetVerticalPanExtent = function(self)
return self.verticalPanExtent
end
ScrollFrame.SetVerticalPanExtent = function(self, panExtent)
self.verticalPanExtent = panExtent
end
ScrollFrame:SetHorizontalPanExtent(30)
ScrollFrame:SetVerticalPanExtent(30)
local ScrollBarV = CreateFrame("EventFrame", nil, self, "WowTrimScrollBar")
ScrollBarV:SetHideIfUnscrollable(true)
ScrollBarV:SetHideTrackIfThumbExceedsTrack(true)
ScrollBarV:SetPoint("TOPLEFT", ScrollFrame, "TOPRIGHT")
ScrollBarV:SetPoint("BOTTOMLEFT", ScrollFrame, "BOTTOMRIGHT")
ScrollBarV:Show()
local ScrollBarH = CreateFrame("EventFrame", nil, self, "WowTrimHorizontalScrollBar")
ScrollBarH:SetHideIfUnscrollable(true)
ScrollBarH:SetHideTrackIfThumbExceedsTrack(true)
ScrollBarH:SetPoint("TOPLEFT", ScrollFrame, "BOTTOMLEFT")
ScrollBarH:SetPoint("TOPRIGHT", ScrollFrame, "BOTTOMRIGHT")
ScrollBarH:Show()
---
-- The below is largely just adapted from InitScrollFrameWithScrollBar
-- but with additional scripts and tweaks to support bidirectional scrolling.
---
local function CalculateScrollPercentage(scrollOffset, scrollRange)
local scrollPercentage = 0
if scrollRange > 0 then
scrollPercentage = scrollOffset / scrollRange
end
return scrollPercentage
end
local function CalculateVisibleExtentPercentage(scrollExtent, scrollRange)
local visibleExtentPercentage = 0
if scrollExtent > 0 then
visibleExtentPercentage = scrollExtent / (scrollRange + scrollExtent)
end
return visibleExtentPercentage
end
local function CalculatePanExtentPercentage(panExtent, scrollRange)
local panExtentPercentage = 0
if scrollRange > 0 then
panExtentPercentage = Saturate(panExtent / scrollRange)
end
return panExtentPercentage
end
local function OnHorizontalScroll(self, offset)
local scrollPercentage = CalculateScrollPercentage(offset, ScrollFrame:GetHorizontalScrollRange())
ScrollBarH:SetScrollPercentage(scrollPercentage, ScrollBoxConstants.NoScrollInterpolation)
end
local function OnVerticalScroll(self, offset)
local scrollPercentage = CalculateScrollPercentage(offset, ScrollFrame:GetVerticalScrollRange())
ScrollBarV:SetScrollPercentage(scrollPercentage, ScrollBoxConstants.NoScrollInterpolation)
end
local function OnScrollRangeChanged(self, hScrollRange, vScrollRange)
OnHorizontalScroll(self, self:GetHorizontalScroll())
OnVerticalScroll(self, self:GetVerticalScroll())
ScrollBarH:SetVisibleExtentPercentage(CalculateVisibleExtentPercentage(self:GetWidth(), hScrollRange))
ScrollBarH:SetPanExtentPercentage(CalculatePanExtentPercentage(self:GetHorizontalPanExtent(), hScrollRange))
ScrollBarV:SetVisibleExtentPercentage(CalculateVisibleExtentPercentage(self:GetHeight(), vScrollRange))
ScrollBarV:SetPanExtentPercentage(CalculatePanExtentPercentage(self:GetVerticalPanExtent(), vScrollRange))
end
local function OnHorizontalBarScroll(self, scrollPercentage)
local scroll = scrollPercentage * ScrollFrame:GetHorizontalScrollRange()
ScrollFrame:SetHorizontalScroll(scroll)
end
local function OnVerticalBarScroll(self, scrollPercentage)
local scroll = scrollPercentage * ScrollFrame:GetVerticalScrollRange()
ScrollFrame:SetVerticalScroll(scroll)
end
local function OnMouseWheel(_, value)
ScrollBarV:ScrollStepInDirection(-value)
end
ScrollFrame:SetScript("OnHorizontalScroll", OnHorizontalScroll)
ScrollFrame:SetScript("OnVerticalScroll", OnVerticalScroll)
ScrollFrame:SetScript("OnScrollRangeChanged", OnScrollRangeChanged)
ScrollFrame:SetScript("OnMouseWheel", OnMouseWheel)
ScrollBarH:RegisterCallback("OnScroll", OnHorizontalBarScroll, ScrollFrame)
ScrollBarV:RegisterCallback("OnScroll", OnVerticalBarScroll, ScrollFrame)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment