您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
An userscript to provide Opera(old) like scrolling behavior.
当前为
// ==UserScript== // @name Scroll like Opera // @description An userscript to provide Opera(old) like scrolling behavior. // @namespace eight04.blogspot.com // @include http* // @version 2.0.3 // @require https://gf.qytechs.cn/scripts/7212-gm-config-eight-s-version/code/GM_config%20(eight's%20version).js?version=29833 // @require https://gf.qytechs.cn/scripts/7108-bezier-easing/code/bezier-easing.js?version=29098 // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // ==/UserScript== (function(){ "use strict"; var config; GM_config.init( "Scroll like Opera", { useWhenOnScrollbar: { label: "Scroll horizontally if cursor hover on horizontal scrollbar.", type: "checkbox", default: true }, useWhenOneScrollbar: { label: "Scroll horizontally if there is only horizontal scrollbar presented.", type: "checkbox", default: true }, useAlways: { label: "Always use script's scrolling handler. Enable this if you want to use the script's smooth scrolling on chrome.", type: "checkbox", default: false }, scrollDelay: { label: "Smooth scrolling delay.", type: "text", default: 400 }, scrollOffset: { label: "Scrolling offset.", type: "text", default: 120 } } ); config = GM_config.get(); GM_registerMenuCommand("Scroll like Opera - Configure", function(){ GM_config.open(); }); GM_config.onclose = function(){ config = GM_config.get(); }; /** Register event */ window.addEventListener("wheel", function(e){ var q = getScrollInfo(e.target, e); if (q && (q.use || config.useAlways)) { e.preventDefault(); scroll(q.element, q.offsetX, q.offsetY); } }); /** Main logic */ function getInfo(element, e) { var rect, css; if (element != document.documentElement) { rect = element.getBoundingClientRect(); css = getCss(element); return { element: element, onScrollbarX: element.clientHeight && e.clientY >= rect.top + css.borderTop + element.clientHeight && e.clientY <= rect.bottom - css.borderBottom, scrollableX: element.clientWidth && element.scrollWidth > element.clientWidth && css.overflowX != "visible" && css.overflowX != "hidden", scrollableY: element.clientHeight && element.scrollHeight > element.clientHeight && css.overflowY != "visible" && css.overflowY != "hidden" }; } else { return { element: element, onScrollbarX: e.clientY >= element.clientHeight && e.clientY <= window.innerHeight, scrollableX: element.scrollWidth > element.clientWidth, scrollableY: element.scrollHeight > element.clientHeight }; } } function getScrollInfo(element, e) { var q; // Get scrollable parent while (element) { q = getInfo(element, e); if (e.deltaY && (q.onScrollbarX || useHorizontalScroll(q)) && scrollable(element, e.deltaY, 0)) { // Horizontal scroll q.offsetX = getOffset(e.deltaY); q.offsetY = 0; q.use = true; return q; } if ((e.deltaX && q.scrollableX || e.deltaY && q.scrollableY) && scrollable(element, e.deltaX, e.deltaY)) { q.offsetX = getOffset(e.deltaX); q.offsetY = getOffset(e.deltaY); return q; } element = element.parentNode; if (element == document) { return null; } } return null; } /** Scroll function. Should I put them into seperate library? Thanks to https://github.com/galambalazs/smoothscroll */ var animate = null; var que = []; function scroll(element, x, y) { var elapsed = config.scrollDelay; que.push({ offsetX: x, offsetY: y, lastX: 0, lastY: 0, element: element, timeStart: null }); if (animate != null) { return; } function animation(timestamp){ var i, j, len, q, time, offsetX, offsetY, process, swap; swap = []; for (i = 0, j = 0, len = que.length; i < len; i++) { q = que[i]; if (q.timeStart == null) { q.timeStart = timestamp; } if (timestamp - q.timeStart >= elapsed || !scrollable(q.element, q.offsetX, q.offsetY)) { scrollBy(q.element, q.offsetX - q.lastX, q.offsetY - q.lastY); } else { time = (timestamp - q.timeStart) / elapsed; process = ease(time); offsetX = Math.floor(q.offsetX * process); offsetY = Math.floor(q.offsetY * process); scrollBy(q.element, offsetX - q.lastX, offsetY - q.lastY); q.lastX = offsetX; q.lastY = offsetY; swap[j++] = q; } } que = swap; if (!que.length) { animate = null; return; } animate = requestAnimationFrame(animation); } animate = requestAnimationFrame(animation); } /** Helpers */ function useHorizontalScroll(q) { return config.useWhenOneScrollbar && q.scrollableX && !q.scrollableY; } function getOffset(delta) { var direction = 0; if (delta > 0) { direction = 1; } else if (delta < 0) { direction = -1; } return direction * config.scrollOffset; } function ease(t){ return BezierEasing.css.ease(t); } function getCss(element){ var css = getComputedStyle(element); return { borderTop: parseInt(css.getPropertyValue("border-top-width"), 10), borderRight: parseInt(css.getPropertyValue("border-right-width"), 10), borderBottom: parseInt(css.getPropertyValue("border-bottom-width"), 10), borderLeft: parseInt(css.getPropertyValue("border-left-width"), 10), overflowX: css.getPropertyValue("overflow-x"), overflowY: css.getPropertyValue("overflow-y") }; } function scrollable(element, offsetX, offsetY) { var top, left; if (element == document.documentElement) { top = window.scrollY; left = window.scrollX; } else { top = element.scrollTop; left = element.scrollLeft; } if (top == 0 && offsetY < 0) { return false; } if (left == 0 && offsetX < 0) { return false; } if (top + element.clientHeight >= element.scrollHeight && offsetY > 0) { return false; } if (left + element.clientWidth >= element.scrollWidth && offsetX > 0) { return false; } return true; } function scrollBy(element, x, y) { if (element != document.documentElement) { element.scrollLeft += x; element.scrollTop += y; } else { window.scrollBy(x, y); } } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址