Greasy Fork

Greasy Fork is available in English.

滚动条-新

为网页添加滚动条。

当前为 2023-07-16 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        滚动条-新
// @namespace   http://greasyfork.icu/zh-CN/users/954189
// @version     1.1
// @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:10px ;width:25px ;line-height:21px ;display: none;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:2vw ;z-index:999999 ;transition: opacity 0.4s ease-in-out; border-radius:1vw "
  );

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

  // 存储文档高度和上次滚动位置
  let docHeight = null;
  let lastScrollTop = null;

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

    // 如果滚动位置改变了,重新计算滚动条位置
    if (scrollTop !== lastScrollTop) {
      const scrollBarTop =
        (scrollTop / docHeight) * (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`;
        docHeight = 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;
    }

    // 显示计算文档高度,并开始更新滚动条位置
    docHeight = 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`;
      docHeight = document.documentElement.scrollHeight - window.innerHeight;
    } else {
      theScrollBar.style.top = `${scrollBarTop}px`;
    }
    const scrollTop =
      (scrollBarTop / (window.innerHeight - theScrollBar.clientHeight)) * docHeight;
    document.documentElement.scrollTop = scrollTop;
  }

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

  // 停止滚动2秒后隐藏
  let timer;
  window.addEventListener("scroll", function() {
    clearTimeout(timer);
      theScrollBar.style.opacity = "0.8";
      theScrollBar.style.display = "block";
    timer = setTimeout(() => {
      theScrollBar.style.opacity = "0";
      setTimeout(function() {
        theScrollBar.style.display = "none";
      }, 400);
    }, 1600);
  });

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

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

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

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

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

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


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

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

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