滚动条-新

为网页添加滚动条。

// ==UserScript==
// @name        滚动条-新
// @namespace   https://greasyfork.org/zh-CN/users/954189
// @version     1.2
// @description 为网页添加滚动条。
// @author      chatgpt
// @run-at      document-end
// @license     MIT
// @match       *://*/*
// ==/UserScript==

(function() {
  'use strict';

  // 创建滚动条 DOM 元素
  const theScrollBar = document.createElement("div");

  // 设置滚动条的 ID 和文本
  theScrollBar.id = "theScrollBar";
  theScrollBar.innerHTML = "▲<br>▼";

  // 设置滚动条样式
  theScrollBar.setAttribute(
    "style",
    "font-size:1.5vw ;width:6vw ;line-height:5vw ;display: block;text-align:center ;background-color:rgba(255,255,255) ;opacity: 0 ;box-shadow:0px 1px 5px rgba(0,0,0,0.2) ;color:#000 ;position:fixed ;top: -14vw;right:-10vw ;z-index:9999999 ;transition: opacity 0.4s ease-in-out,right 0.4s; border-radius:1vw "
  );

  // 将滚动条元素添加到页面中
  document.body.appendChild(theScrollBar);

  // 存储网页高度和上次滚动位置
  let webHeight = null;
  let lastScrollTop = null;

  // 更新滚动条位置的函数
  function updateScrollBar() {
    // 获取当前的滚动位置
    const scrollTop = window.scrollY;

    // 如果滚动位置改变了,重新计算滚动条位置
    if (scrollTop !== lastScrollTop) {
      const scrollBarTop =
        (scrollTop / webHeight) * (window.innerHeight - theScrollBar.clientHeight);
      if (scrollBarTop < 0) {
        theScrollBar.style.top = "0";
      } else if (scrollBarTop + theScrollBar.clientHeight > window.innerHeight) {
        theScrollBar.style.top = `${window.innerHeight - theScrollBar.clientHeight}px`;
        webHeight = document.documentElement.scrollHeight - window.innerHeight;
      } else {
        theScrollBar.style.top = `${scrollBarTop}px`;
      }
      lastScrollTop = scrollTop;
    }

    // 使用 requestAnimationFrame 函数,优化渲染性能
    window.requestAnimationFrame(updateScrollBar);
  }

  // 添加 touchstart 事件监听器,当用户在手机上开始触摸屏幕时触发
  window.addEventListener("touchstart", function() {
    //如果网页高度过低,不需要添加滚动条
    if (document.documentElement.scrollHeight <= window.innerHeight * 2) {
      return;
    }

    // 获取网页高度,并开始更新滚动条位置
    webHeight = document.documentElement.scrollHeight - window.innerHeight;
    updateScrollBar();
  });

  // 定义一些与触摸事件相关的变量
  let startOffset = null;

  // 滚动条开始滚动时触发的函数
  function startScroll(event) {
    event.preventDefault();
    event.stopPropagation();
    startOffset = event.changedTouches[0].clientY - parseInt(theScrollBar.style.top);
  }

  // 滚动条正在滚动时触发的函数
  function scrolling(event) {
    event.preventDefault();
    event.stopPropagation();
    // 计算当前滚动条的位置和滑动距离,并更新滚动位置和滚动条位置
    const currentY = event.changedTouches[0].clientY;
    const scrollBarTop = currentY - startOffset;
    if (scrollBarTop < 0) {
      theScrollBar.style.top = "0px";
    } else if (scrollBarTop > window.innerHeight - theScrollBar.clientHeight) {
      theScrollBar.style.top = `${window.innerHeight - theScrollBar.clientHeight}px`;
      webHeight = document.documentElement.scrollHeight - window.innerHeight;
    } else {
      theScrollBar.style.top = `${scrollBarTop}px`;
    }
    const scrollTop =
      (scrollBarTop / (window.innerHeight - theScrollBar.clientHeight)) * webHeight;
    window.scrollTo(window.scrollX, scrollTop);
  }

  // 为滚动条添加触摸事件监听器
  theScrollBar.addEventListener("touchstart", startScroll, { passive: false });
  theScrollBar.addEventListener("touchmove", scrolling, { passive: false });

  // 停止滚动1秒后隐藏
  let timer;
  window.addEventListener("scroll", function() {
    clearTimeout(timer);
    theScrollBar.style.right = "2vw";
    theScrollBar.style.opacity = "0.8";
    timer = setTimeout(() => {
      theScrollBar.style.right = "-10vw";
      theScrollBar.style.opacity = "0";
    }, 1000);
  });

  // 定义触顶/底反弹动画的函数
  function bounceAnimation() {
    // 获取当前滚动条的位置
    const scrollTop = window.scrollY;

    // 获取滚动条的高度
    const scrollBarHeight = theScrollBar.clientHeight;

    // 获取滚动速度
    const scrollSpeed = Math.abs(scrollTop - lastScrollTop);

    // 设置滚动速度阈值
    const threshold = 7;

    // 如果滚动条触顶,且滚动速度超过阈值,执行反弹动画
    if (scrollTop === 0 && scrollSpeed > threshold) {
      theScrollBar.style.animation = "bounce-down 0.4s";
      setTimeout(() => {
        theScrollBar.style.animation = "";
      }, 500);
    }

    // 如果滚动条触底,且滚动速度超过阈值,执行反弹动画
    if (scrollTop + window.innerHeight >= document.documentElement.scrollHeight && scrollSpeed > threshold) {
      theScrollBar.style.animation = "bounce-up 0.4s";
      setTimeout(() => {
        theScrollBar.style.animation = "";
      }, 500);
    }
  }

  // 添加触顶/底反弹动画的事件监听器
  window.addEventListener("scroll", bounceAnimation);

  // CSS样式
  const styles = `
  @keyframes bounce-down {
    0% {
      transform: translateY(0);
    }
    30% {
      transform: translateY(10px);
    }
    100% {
      transform: translateY(0);
    } 
  }
  @keyframes bounce-up {
    0% {
      transform: translateY(0);
    }
     30% {
      transform: translateY(-10px);
    }
    100% {
      transform: translateY(0);
    }
  }
  `;

  // 创建样式元素并将样式添加到头部
  const styleElement = document.createElement("style");
  styleElement.innerHTML = styles;
  document.head.appendChild(styleElement);


})();