From 9b03d2790b8b8db1b5a6755b6130f37e5f7f2455 Mon Sep 17 00:00:00 2001 From: Kyren223 Date: Thu, 8 Oct 2026 19:44:46 +0300 Subject: WIP --- public/scrollbar.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 public/scrollbar.js (limited to 'public/scrollbar.js') diff --git a/public/scrollbar.js b/public/scrollbar.js new file mode 100644 index 0000000..da6aded --- /dev/null +++ b/public/scrollbar.js @@ -0,0 +1,52 @@ +function initScrollbox(box) { + const area = box.querySelector("[data-scroll-area]"); + const track = box.querySelector("[data-scroll-track]"); + const thumb = box.querySelector("[data-scroll-thumb]"); + + const inset = () => parseFloat(getComputedStyle(thumb).left) || 0; + + const update = () => { + const pad = inset(); + const room = track.clientHeight - pad * 2; + const maxScroll = area.scrollHeight - area.clientHeight; + const ratio = Math.min(1, area.clientHeight / area.scrollHeight); + const height = Math.max(room * ratio, thumb.clientWidth); + const progress = maxScroll > 0 ? area.scrollTop / maxScroll : 0; + thumb.style.height = `${height}px`; + thumb.style.top = `${pad + progress * (room - height)}px`; + }; + + thumb.addEventListener("pointerdown", (e) => { + e.preventDefault(); + thumb.setPointerCapture(e.pointerId); + const startY = e.clientY; + const startTop = parseFloat(thumb.style.top) || 0; + + const move = (ev) => { + const pad = inset(); + const room = track.clientHeight - pad * 2 - thumb.offsetHeight; + const top = Math.min( + Math.max(startTop - pad + ev.clientY - startY, 0), + room, + ); + const progress = room > 0 ? top / room : 0; + area.scrollTop = progress * (area.scrollHeight - area.clientHeight); + }; + const stop = () => { + thumb.removeEventListener("pointermove", move); + thumb.removeEventListener("pointerup", stop); + thumb.removeEventListener("pointercancel", stop); + }; + thumb.addEventListener("pointermove", move); + thumb.addEventListener("pointerup", stop); + thumb.addEventListener("pointercancel", stop); + }); + + area.addEventListener("scroll", update, { passive: true }); + const observer = new ResizeObserver(update); + observer.observe(area); + for (const child of area.children) observer.observe(child); + update(); +} + +document.querySelectorAll("[data-scrollbox]").forEach(initScrollbox); -- cgit v1.3.1