页面滚动条美化

页面窗口侧边栏美化

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name                页面滚动条美化
// @description         页面窗口侧边栏美化
//
// @author              xiao
// @license             GPLv3.0
// @namespace           https://github.com/xiaoboost
// @supportURL          https://github.com/xiaoboost/scripts/issues
// @homepageURL         https://github.com/xiaoboost/scripts/tree/master/packages/scrollbar
//
// @grant               GM_addStyle
// @grant               unsafeWindow
// @run-at              document-start
// @include             *
//
// @date                2023/10/14
// @modified            2023/10/14
// @version             1.0.1
// ==/UserScript==

(() => {
  // ../../node_modules/.pnpm/registry.npmmirror.com+@[email protected]/node_modules/@xiao-ai/utils/dist/esm/web/env.js
  var inBrowser = typeof window !== "undefined";
  var UA = inBrowser && window.navigator.userAgent.toLowerCase();
  var isIE = UA && /msie|trident/.test(UA);
  var isIE9 = UA && UA.indexOf("msie 9.0") > 0;
  var isEdge = UA && UA.indexOf("edge/") > 0;
  var isAndroid = UA && UA.indexOf("android") > 0;
  var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);
  var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
  var supportsPassive = false;
  var supportsOnce = false;
  if (inBrowser) {
    try {
      document.body.addEventListener("test", null, Object.defineProperty({}, "passive", {
        get() {
          supportsPassive = true;
        }
      }));
    } catch (e) {
    }
    try {
      document.body.addEventListener("test", null, Object.defineProperty({}, "once", {
        get() {
          supportsOnce = true;
        }
      }));
    } catch (e) {
    }
  }

  // ../../node_modules/.pnpm/registry.npmmirror.com+@[email protected]/node_modules/@xiao-ai/utils/dist/esm/web/event.js
  var MouseButtons;
  (function(MouseButtons2) {
    MouseButtons2[MouseButtons2["Left"] = 0] = "Left";
    MouseButtons2[MouseButtons2["Middle"] = 1] = "Middle";
    MouseButtons2[MouseButtons2["Right"] = 2] = "Right";
    MouseButtons2[MouseButtons2["Back"] = 3] = "Back";
    MouseButtons2[MouseButtons2["Forward"] = 4] = "Forward";
  })(MouseButtons || (MouseButtons = {}));

  // ../../node_modules/.pnpm/registry.npmmirror.com+@[email protected]/node_modules/@xiao-ai/utils/dist/esm/web/class-name.js
  function addClassName(el, className) {
    var _a;
    const classNameTrim = className.trim();
    const oldClassNames = ((_a = el.getAttribute("class")) !== null && _a !== void 0 ? _a : "").split(/\s+/);
    if (oldClassNames.includes(classNameTrim)) {
      return;
    }
    const newCLassNames = oldClassNames.concat(className.trim()).join(" ");
    el.setAttribute("class", newCLassNames);
  }
  function removeClassName(el, className) {
    var _a;
    const classNameTrim = className.trim();
    const oldClassNames = ((_a = el.getAttribute("class")) !== null && _a !== void 0 ? _a : "").split(/\s+/);
    if (!oldClassNames.includes(classNameTrim)) {
      return;
    }
    const newCLassNames = oldClassNames.filter((name) => name !== classNameTrim).join(" ");
    el.setAttribute("class", newCLassNames);
  }

  // ../utils/src/style.ts
  var codes = [];
  var timer = -1;
  function addStyle(code) {
    codes.push(code);
    if (timer !== -1) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      GM_addStyle(codes.join("\n"));
      if (false) {
        log("\u6837\u5F0F\u5143\u7D20\u52A0\u8F7D\u6210\u529F");
        timer = -1;
        codes.length = 0;
      }
    });
  }

  // ../utils/src/web.ts
  function onLoadStart(cb) {
    if (document.readyState === "interactive") {
      cb();
    }
    document.addEventListener("DOMContentLoaded", cb);
  }

  // ../../node_modules/.pnpm/[email protected]/node_modules/current-device/es/index.js
  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
    return typeof obj;
  } : function(obj) {
    return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  };
  var previousDevice = window.device;
  var device = {};
  var changeOrientationList = [];
  window.device = device;
  var documentElement = window.document.documentElement;
  var userAgent = window.navigator.userAgent.toLowerCase();
  var television = ["googletv", "viera", "smarttv", "internet.tv", "netcast", "nettv", "appletv", "boxee", "kylo", "roku", "dlnadoc", "pov_tv", "hbbtv", "ce-html"];
  device.macos = function() {
    return find("mac");
  };
  device.ios = function() {
    return device.iphone() || device.ipod() || device.ipad();
  };
  device.iphone = function() {
    return !device.windows() && find("iphone");
  };
  device.ipod = function() {
    return find("ipod");
  };
  device.ipad = function() {
    var iPadOS13Up = navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
    return find("ipad") || iPadOS13Up;
  };
  device.android = function() {
    return !device.windows() && find("android");
  };
  device.androidPhone = function() {
    return device.android() && find("mobile");
  };
  device.androidTablet = function() {
    return device.android() && !find("mobile");
  };
  device.blackberry = function() {
    return find("blackberry") || find("bb10");
  };
  device.blackberryPhone = function() {
    return device.blackberry() && !find("tablet");
  };
  device.blackberryTablet = function() {
    return device.blackberry() && find("tablet");
  };
  device.windows = function() {
    return find("windows");
  };
  device.windowsPhone = function() {
    return device.windows() && find("phone");
  };
  device.windowsTablet = function() {
    return device.windows() && find("touch") && !device.windowsPhone();
  };
  device.fxos = function() {
    return (find("(mobile") || find("(tablet")) && find(" rv:");
  };
  device.fxosPhone = function() {
    return device.fxos() && find("mobile");
  };
  device.fxosTablet = function() {
    return device.fxos() && find("tablet");
  };
  device.meego = function() {
    return find("meego");
  };
  device.cordova = function() {
    return window.cordova && location.protocol === "file:";
  };
  device.nodeWebkit = function() {
    return _typeof(window.process) === "object";
  };
  device.mobile = function() {
    return device.androidPhone() || device.iphone() || device.ipod() || device.windowsPhone() || device.blackberryPhone() || device.fxosPhone() || device.meego();
  };
  device.tablet = function() {
    return device.ipad() || device.androidTablet() || device.blackberryTablet() || device.windowsTablet() || device.fxosTablet();
  };
  device.desktop = function() {
    return !device.tablet() && !device.mobile();
  };
  device.television = function() {
    var i = 0;
    while (i < television.length) {
      if (find(television[i])) {
        return true;
      }
      i++;
    }
    return false;
  };
  device.portrait = function() {
    if (screen.orientation && Object.prototype.hasOwnProperty.call(window, "onorientationchange")) {
      return includes(screen.orientation.type, "portrait");
    }
    if (device.ios() && Object.prototype.hasOwnProperty.call(window, "orientation")) {
      return Math.abs(window.orientation) !== 90;
    }
    return window.innerHeight / window.innerWidth > 1;
  };
  device.landscape = function() {
    if (screen.orientation && Object.prototype.hasOwnProperty.call(window, "onorientationchange")) {
      return includes(screen.orientation.type, "landscape");
    }
    if (device.ios() && Object.prototype.hasOwnProperty.call(window, "orientation")) {
      return Math.abs(window.orientation) === 90;
    }
    return window.innerHeight / window.innerWidth < 1;
  };
  device.noConflict = function() {
    window.device = previousDevice;
    return this;
  };
  function includes(haystack, needle) {
    return haystack.indexOf(needle) !== -1;
  }
  function find(needle) {
    return includes(userAgent, needle);
  }
  function hasClass(className) {
    return documentElement.className.match(new RegExp(className, "i"));
  }
  function addClass(className) {
    var currentClassNames = null;
    if (!hasClass(className)) {
      currentClassNames = documentElement.className.replace(/^\s+|\s+$/g, "");
      documentElement.className = currentClassNames + " " + className;
    }
  }
  function removeClass(className) {
    if (hasClass(className)) {
      documentElement.className = documentElement.className.replace(" " + className, "");
    }
  }
  if (device.ios()) {
    if (device.ipad()) {
      addClass("ios ipad tablet");
    } else if (device.iphone()) {
      addClass("ios iphone mobile");
    } else if (device.ipod()) {
      addClass("ios ipod mobile");
    }
  } else if (device.macos()) {
    addClass("macos desktop");
  } else if (device.android()) {
    if (device.androidTablet()) {
      addClass("android tablet");
    } else {
      addClass("android mobile");
    }
  } else if (device.blackberry()) {
    if (device.blackberryTablet()) {
      addClass("blackberry tablet");
    } else {
      addClass("blackberry mobile");
    }
  } else if (device.windows()) {
    if (device.windowsTablet()) {
      addClass("windows tablet");
    } else if (device.windowsPhone()) {
      addClass("windows mobile");
    } else {
      addClass("windows desktop");
    }
  } else if (device.fxos()) {
    if (device.fxosTablet()) {
      addClass("fxos tablet");
    } else {
      addClass("fxos mobile");
    }
  } else if (device.meego()) {
    addClass("meego mobile");
  } else if (device.nodeWebkit()) {
    addClass("node-webkit");
  } else if (device.television()) {
    addClass("television");
  } else if (device.desktop()) {
    addClass("desktop");
  }
  if (device.cordova()) {
    addClass("cordova");
  }
  function handleOrientation() {
    if (device.landscape()) {
      removeClass("portrait");
      addClass("landscape");
      walkOnChangeOrientationList("landscape");
    } else {
      removeClass("landscape");
      addClass("portrait");
      walkOnChangeOrientationList("portrait");
    }
    setOrientationCache();
  }
  function walkOnChangeOrientationList(newOrientation) {
    for (var index = 0; index < changeOrientationList.length; index++) {
      changeOrientationList[index](newOrientation);
    }
  }
  device.onChangeOrientation = function(cb) {
    if (typeof cb == "function") {
      changeOrientationList.push(cb);
    }
  };
  var orientationEvent = "resize";
  if (Object.prototype.hasOwnProperty.call(window, "onorientationchange")) {
    orientationEvent = "orientationchange";
  }
  if (window.addEventListener) {
    window.addEventListener(orientationEvent, handleOrientation, false);
  } else if (window.attachEvent) {
    window.attachEvent(orientationEvent, handleOrientation);
  } else {
    window[orientationEvent] = handleOrientation;
  }
  handleOrientation();
  function findMatch(arr) {
    for (var i = 0; i < arr.length; i++) {
      if (device[arr[i]]()) {
        return arr[i];
      }
    }
    return "unknown";
  }
  device.type = findMatch(["mobile", "tablet", "desktop"]);
  device.os = findMatch(["ios", "iphone", "ipad", "ipod", "android", "blackberry", "macos", "windows", "fxos", "meego", "television"]);
  function setOrientationCache() {
    device.orientation = findMatch(["portrait", "landscape"]);
  }
  setOrientationCache();
  var es_default = device;

  // src/style.jss.ts
  var style_jss_default = {
    classes: {
      "scrollbarInvisible": "script-scrollbar-invisible-0",
      "scrollbarVisible": "script-scrollbar-visible-0",
      "scrollbarSlider": "script-scrollbar-slider-0",
      "scrollbarDisable": "script-scrollbar-disable-0",
      "scrollbarContainer": "script-scrollbar-container-0"
    },
    toString: function() {
      return `.script-scrollbar-container-0 {
  top: 0;
  right: 0;
  z-index: 999;
  position: absolute;
  background: transparent;
}
.script-scrollbar-container-0.script-scrollbar-invisible-0 {
  opacity: 0;
  transition: opacity .5s linear;
}
.script-scrollbar-container-0.script-scrollbar-visible-0 {
  opacity: 1;
  transition: opacity .2s linear;
}
.script-scrollbar-container-0.script-scrollbar-disable-0 {
  display: none;
  pointer-events: none;
}
.script-scrollbar-container-0 .script-scrollbar-slider-0 {
  left: 0;
  contain: strict;
  position: absolute;
  transform: translate3d(0px, 0px, 0px);
  background: rgba(100, 100, 100, 0.5);
}
body::-webkit-scrollbar {
  width: 0 !important;
  display: none;
}
body::-webkit-scrollbar-track {
  display: none;
}
body::-webkit-scrollbar-thumb {
  display: none;
}`;
    }
  };

  // src/scrollbar.ts
  var { classes: cla } = style_jss_default;
  var ScrollBar = class {
    scrollbar;
    slider;
    width = 10;
    hideScrollTimer = -1;
    mouse = {
      isMoving: false,
      isOver: false,
      offset: -1,
      lastOffset: -1
    };
    constructor() {
      if (document.querySelector(".cla.scrollbarContainer")) {
        return;
      }
      this.scrollbar = document.createElement("div");
      this.slider = document.createElement("div");
      this.scrollbar.appendChild(this.slider);
      this.scrollbar.setAttribute("class", `${cla.scrollbarContainer} ${cla.scrollbarInvisible}`);
      this.slider.setAttribute("class", cla.scrollbarSlider);
      document.body.appendChild(this.scrollbar);
      this.init();
    }
    get clientLength() {
      return this.container.clientHeight;
    }
    get scrollLength() {
      return this.container.scrollHeight;
    }
    get container() {
      return document.documentElement;
    }
    init() {
      const {
        container,
        scrollbar,
        slider,
        scrollLength,
        clientLength,
        width,
        mouse
      } = this;
      if (!es_default.desktop()) {
        addClassName(scrollbar, cla.scrollbarDisable);
        return;
      }
      addStyle(style_jss_default.toString());
      if (scrollLength <= clientLength) {
        scrollbar.style.display = "none";
        return;
      }
      scrollbar.style.height = "100%";
      scrollbar.style.width = `${width}px`;
      slider.style.width = `${width}px`;
      this.setSliderPositionFromContainer();
      const options = !supportsPassive ? false : {
        passive: true,
        capture: false
      };
      const triggerTrue = () => {
        mouse.isOver = true;
        this.triggerClass(true);
      };
      const triggerFalse = () => {
        mouse.isOver = false;
        this.delaySetScrollInvisible();
      };
      const startMouseMove = (ev) => {
        if (!mouse.isMoving && ev.button === MouseButtons.Left) {
          mouse.isMoving = true;
          container.style.userSelect = "none";
          container.style.cursor = "s-resize";
        }
      };
      const stopMouseMove = () => {
        const { mouse: mouse2, container: container2 } = this;
        if (mouse2.isMoving) {
          mouse2.offset = -1;
          mouse2.lastOffset = -1;
          mouse2.isMoving = false;
          container2.style.userSelect = "";
          container2.style.cursor = "";
        }
        this.delaySetScrollInvisible();
      };
      scrollbar.style.position = "fixed";
      scrollbar.addEventListener("mouseenter", triggerTrue, options);
      scrollbar.addEventListener("mouseleave", triggerFalse, options);
      slider.addEventListener("mousedown", startMouseMove, options);
      window.addEventListener("mouseup", stopMouseMove, options);
      window.addEventListener("mousemove", this.setSliderPositionFromMouse, options);
      window.addEventListener("resize", this.setSliderPositionFromContainer, options);
      window.addEventListener("scroll", this.setSliderPositionFromContainer, options);
      container.addEventListener("scroll", this.setSliderPositionFromContainer, options);
      this.disable = () => {
        stopMouseMove();
        scrollbar.removeEventListener("mouseenter", triggerTrue, options);
        scrollbar.removeEventListener("mouseleave", triggerFalse, options);
        slider.removeEventListener("mousedown", startMouseMove, options);
        window.removeEventListener("mouseup", stopMouseMove, options);
        window.removeEventListener("mousemove", this.setSliderPositionFromMouse, options);
        window.removeEventListener("resize", this.setSliderPositionFromContainer, options);
        window.removeEventListener("scroll", this.setSliderPositionFromContainer, options);
        container.removeEventListener("scroll", this.setSliderPositionFromContainer, options);
      };
    }
    disable = () => void 0;
    setSliderPositionFromContainer = () => {
      const { mouse } = this;
      if (mouse.isMoving) {
        return;
      }
      const {
        clientLength: client,
        scrollLength: scroll,
        container: parent,
        slider
      } = this;
      const scrollbarLen = client / scroll * client;
      const scrollOffset = parent.scrollTop / scroll * client;
      mouse.offset = scrollOffset;
      this.triggerClass(true);
      this.delaySetScrollInvisible();
      slider.style.height = `${scrollbarLen}px`;
      slider.style.top = `${scrollOffset}px`;
    };
    setSliderPositionFromMouse = (ev) => {
      const { mouse } = this;
      if (!mouse.isMoving) {
        return;
      }
      const { clientLength: client, scrollLength: scroll, slider } = this;
      const currentOffset = ev.clientY;
      if (mouse.offset === -1) {
        mouse.offset = Number.parseFloat(slider.style.top);
      }
      if (mouse.lastOffset === -1) {
        mouse.lastOffset = currentOffset;
        return;
      }
      const offsetY = currentOffset - mouse.lastOffset;
      const scrollbarLen = client / scroll * client;
      mouse.lastOffset = currentOffset;
      mouse.offset += offsetY;
      let realOffset = mouse.offset;
      if (realOffset < 0) {
        realOffset = 0;
      }
      if (realOffset > client - scrollbarLen) {
        realOffset = client - scrollbarLen;
      }
      slider.style.top = `${realOffset}px`;
      window.scrollTo({
        top: realOffset / client * scroll,
        behavior: "auto"
      });
    };
    delaySetScrollInvisible = () => {
      if (this.hideScrollTimer !== -1) {
        clearTimeout(this.hideScrollTimer);
      }
      this.hideScrollTimer = window.setTimeout(() => {
        if (this.mouse.isOver || this.mouse.isMoving) {
          return;
        }
        this.triggerClass(false);
      }, 300);
    };
    triggerClass = (visible) => {
      removeClassName(this.scrollbar, visible ? cla.scrollbarInvisible : cla.scrollbarVisible);
      addClassName(this.scrollbar, visible ? cla.scrollbarVisible : cla.scrollbarInvisible);
    };
  };

  // src/index.ts
  onLoadStart(() => new ScrollBar());
})();