页面滚动条美化

页面窗口侧边栏美化

// ==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());
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址