Mobile Draggable Scrollbar

모바일 브라우저에 반투명한 스크롤바 추가하고 드래그 가능하게 만듦 (최소 크기 및 터치 개선)

Verze ze dne 24. 02. 2025. Zobrazit nejnovější verzi.

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         Mobile Draggable Scrollbar
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  모바일 브라우저에 반투명한 스크롤바 추가하고 드래그 가능하게 만듦 (최소 크기 및 터치 개선)
// @author       ChatGPT
// @license      MIT
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // 스타일 적용
    const style = document.createElement("style");
    style.textContent = `
        .custom-scrollbar-container {
            position: fixed;
            right: 3px;
            top: 0;
            width: 14px; /* 터치 영역을 넓히기 위해 큰 컨테이너 */
            height: 100%;
            z-index: 9999;
            pointer-events: none;
        }
        
        .custom-scrollbar {
            position: absolute;
            right: 3px;
            width: 8px;
            background: rgba(0, 0, 0, 0.4);
            border-radius: 4px;
            opacity: 0;
            transition: opacity 0.3s ease-in-out;
            touch-action: none; /* 터치 드래그 활성화 */
            pointer-events: auto;
        }
        
        .custom-scrollbar.active {
            background: rgba(0, 0, 0, 0.6); /* 터치 중일 때 색상 강조 */
        }
    `;
    document.head.appendChild(style);

    // 스크롤바 컨테이너 생성 (터치 영역 확대용)
    const scrollbarContainer = document.createElement("div");
    scrollbarContainer.classList.add("custom-scrollbar-container");
    document.body.appendChild(scrollbarContainer);

    // 스크롤바 요소 생성
    const scrollbar = document.createElement("div");
    scrollbar.classList.add("custom-scrollbar");
    scrollbarContainer.appendChild(scrollbar);

    let timeoutId = null;
    let isDragging = false;
    let startY = 0;
    let startScrollTop = 0;

    function updateScrollbar() {
        const scrollHeight = document.documentElement.scrollHeight;
        const clientHeight = window.innerHeight;
        const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;

        if (scrollHeight <= clientHeight) {
            scrollbar.style.opacity = "0"; // 스크롤이 필요 없는 경우 숨김
            return;
        }

        // 최소 크기 적용 (너무 작아지지 않도록)
        const minScrollbarHeight = 40;
        let scrollbarHeight = Math.max((clientHeight / scrollHeight) * clientHeight, minScrollbarHeight);

        // 스크롤 위치 비율 계산
        const maxScrollTop = scrollHeight - clientHeight;
        const maxScrollbarTop = clientHeight - scrollbarHeight;
        let scrollbarTop = (scrollTop / maxScrollTop) * maxScrollbarTop;

        scrollbar.style.height = `${scrollbarHeight}px`;
        scrollbar.style.top = `${scrollbarTop}px`;
        scrollbar.style.opacity = "1";

        // 일정 시간이 지나면 서서히 사라짐
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
            if (!isDragging) {
                scrollbar.style.opacity = "0";
            }
        }, 800);
    }

    function startDrag(event) {
        isDragging = true;
        scrollbar.classList.add("active");

        startY = event.touches ? event.touches[0].clientY : event.clientY;
        startScrollTop = document.documentElement.scrollTop || document.body.scrollTop;

        event.preventDefault();
    }

    function onDrag(event) {
        if (!isDragging) return;

        const currentY = event.touches ? event.touches[0].clientY : event.clientY;
        const deltaY = currentY - startY;

        const scrollHeight = document.documentElement.scrollHeight;
        const clientHeight = window.innerHeight;
        const maxScrollTop = scrollHeight - clientHeight;

        const minScrollbarHeight = 40;
        const scrollbarHeight = Math.max((clientHeight / scrollHeight) * clientHeight, minScrollbarHeight);
        const maxScrollbarTop = clientHeight - scrollbarHeight;
        const scrollRatio = maxScrollTop / maxScrollbarTop;

        document.documentElement.scrollTop = startScrollTop + deltaY * scrollRatio;
        document.body.scrollTop = startScrollTop + deltaY * scrollRatio;

        updateScrollbar();
    }

    function endDrag() {
        isDragging = false;
        scrollbar.classList.remove("active");
        timeoutId = setTimeout(() => {
            scrollbar.style.opacity = "0";
        }, 800);
    }

    // 이벤트 리스너 추가
    scrollbarContainer.addEventListener("touchstart", startDrag);
    window.addEventListener("touchmove", onDrag);
    window.addEventListener("touchend", endDrag);

    scrollbarContainer.addEventListener("mousedown", startDrag);
    window.addEventListener("mousemove", onDrag);
    window.addEventListener("mouseup", endDrag);

    window.addEventListener("scroll", updateScrollbar);
    window.addEventListener("resize", updateScrollbar);

    updateScrollbar();
})();