// ==UserScript== // @name 返回顶部和底部-美化版 // @version 1.1.2 // @description 一个很漂亮的可返回顶部或底部的可拖拽的按钮,支持忽略网站和右键菜单 // @author 沐雨 // @license MIT // @match *://*/* // @grant GM_info // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_getResourceText // @require http://code.jquery.com/jquery-1.11.0.min.js // @namespace https://www.yuxi.com/ // @downloadURL none // ==/UserScript== ; (function () { 'use strict' // 检查是否在iframe中运行 if (window.self !== window.top) { // 在iframe中运行,不执行脚本 return; } // 检查当前网站是否在忽略列表中 const currentHost = window.location.hostname; const ignoredSites = JSON.parse(localStorage.getItem('btnScript_ignoredSites') || '[]'); // 如果当前网站在忽略列表中,则不执行脚本 if (ignoredSites.includes(currentHost)) { return; } var TBLink = function () { var $ = $ || window.$ var $doc = $(document) var $win = $(window) // const iconFont = GM_getResourceText('css') var CreateHtml = function () { var html = `
` $('html body').append(html) // 添加右键菜单 $('#goTopBottom').on('contextmenu', showContextMenu); } // 创建右键菜单 var createContextMenu = function() { var menu = $('
'); menu.css({ position: 'absolute', background: 'white', border: '1px solid #ddd', borderRadius: '8px', boxShadow: '0 3px 10px rgba(0,0,0,0.15)', padding: '5px 0', zIndex: 10000, display: 'none', minWidth: '140px', fontFamily: 'Arial, sans-serif', fontSize: '14px', transition: 'opacity 0.2s ease' }); // 创建关闭选项 var closeOption = $('
关闭按钮
'); closeOption.css({ padding: '10px 15px', cursor: 'pointer', borderRadius: '4px', margin: '2px 5px', transition: 'background-color 0.2s' }); closeOption.hover( function() { $(this).css('backgroundColor', '#f2f2f2'); }, function() { $(this).css('backgroundColor', 'transparent'); } ); closeOption.on('click', hideScrollButtons); // 创建忽略网站选项 var ignoreOption = $('
忽略此网站
'); ignoreOption.css({ padding: '10px 15px', cursor: 'pointer', borderRadius: '4px', margin: '2px 5px', transition: 'background-color 0.2s' }); ignoreOption.hover( function() { $(this).css('backgroundColor', '#f2f2f2'); }, function() { $(this).css('backgroundColor', 'transparent'); } ); ignoreOption.on('click', ignoreCurrentSite); // 添加图标 var closeIcon = ''; var ignoreIcon = ''; closeOption.html(closeIcon + '关闭按钮'); ignoreOption.html(ignoreIcon + '忽略此网站'); menu.append(closeOption); menu.append(ignoreOption); $('body').append(menu); return menu; } // 显示右键菜单 var showContextMenu = function(e) { e.preventDefault(); var menu = $('#gtb-context-menu'); if (menu.length === 0) { menu = createContextMenu(); } // 计算菜单位置,防止溢出视窗 var windowWidth = window.innerWidth; var windowHeight = window.innerHeight; // 先显示菜单但设置为不可见,以便计算尺寸 menu.css({ visibility: 'hidden', display: 'block' }); var menuWidth = menu.outerWidth(); var menuHeight = menu.outerHeight(); // 计算最佳位置,防止菜单溢出窗口 var posX = e.clientX; var posY = e.clientY; // 右侧边界检查 if (posX + menuWidth > windowWidth - 10) { posX = windowWidth - menuWidth - 10; } // 底部边界检查 if (posY + menuHeight > windowHeight - 10) { posY = windowHeight - menuHeight - 10; } // 设置菜单位置并显示 menu.css({ left: posX + 'px', top: posY + 'px', visibility: 'visible', display: 'block' }); // 点击其他区域关闭菜单 setTimeout(function() { $(document).one('click', function() { menu.hide(); }); }, 100); } // 隐藏滚动按钮 var hideScrollButtons = function() { $('#goTopBottom').hide(); } // 忽略当前网站 var ignoreCurrentSite = function() { var currentHost = window.location.hostname; var ignoredSites = JSON.parse(localStorage.getItem('btnScript_ignoredSites') || '[]'); // 添加当前网站到忽略列表 if (!ignoredSites.includes(currentHost)) { ignoredSites.push(currentHost); localStorage.setItem('btnScript_ignoredSites', JSON.stringify(ignoredSites)); } // 隐藏按钮 hideScrollButtons(); } // 用于存储最后拖拽结束的时间戳 var lastDragEndTime = 0; // 拖拽后多长时间内不触发点击(毫秒) var clickPreventionDelay = 500; // 检查是否应该阻止点击 var shouldPreventClick = function() { return Date.now() - lastDragEndTime < clickPreventionDelay; } var CreateStyle = function () { var style = '#goTopBottom {position: fixed;bottom: 75px;right: 15px;z-index: 999999;display: flex;flex-direction: column;row-gap: 5px; opacity: 0.7; transition: opacity 0.3s;}' + '#goTopBottom:hover {opacity: 1;}' + '#goTopBottom .top {opacity: 0;}' + '#goTopBottom .t-btn {display: flex;justify-content: center;align-items: center;width: 40px;height: 40px;cursor: pointer;color: #fff;border-radius: 4px;background-image: linear-gradient(to top right,#6966ff,#37e2d3);background-size: 100% 100%;background-color: transparent;}' + '#goTopBottom .bottom {opacity: 0;}' // GM_addStyle(iconFont) GM_addStyle(style) } var GoTB = function () { var upperLimit = 100 var scrollSpeed = 500 var fadeSpeed = 300 var $top = $('#goTopBottom .gotop') var $bottom = $('#goTopBottom .bottom') if (getScrollTop() > upperLimit) { $top.stop().fadeTo(0, 1, function () { $top.show() }) } if (getScrollTop() + $(window).height() < $doc.height() - upperLimit) { $bottom.stop().fadeTo(0, 1, function () { $bottom.show() }) } $doc.scroll(function () { if (getScrollTop() > upperLimit) { $top.stop().fadeTo(fadeSpeed, 1, function () { $top.css('visibility', 'visible') }) } else { $top.stop().fadeTo(fadeSpeed, 0, function () { $top.css('visibility', 'hidden') }) } if (getScrollTop() + $(window).height() < $doc.height() - upperLimit) { $bottom.stop().fadeTo(fadeSpeed, 1, function () { $bottom.css('visibility', 'visible') }) } else { $bottom.stop().fadeTo(fadeSpeed, 0, function () { $bottom.css('visibility', 'hidden') }) } }) // 移除旧的点击处理器,确保不会重复绑定 $('#goTopBottom span').off('click'); // 添加新的点击处理器 $('#goTopBottom span').on('click', function (e) { // 如果刚拖拽完成,阻止点击 if (shouldPreventClick()) { e.preventDefault(); e.stopPropagation(); return false; } var $this = $(this) var clsName = $this.attr('class') // 改进的滚动处理,处理懒加载内容 if (clsName.includes('gotop')) { // 滚动到顶部 $('html, body').animate({ scrollTop: 0 }, scrollSpeed) } else { // 滚动到底部,处理懒加载内容 const maxScrollHeight = Math.max( document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight ); $('html, body').animate({ scrollTop: maxScrollHeight }, scrollSpeed) } return false }) } var getScrollTop = function () { var scrollTop = $doc.scrollTop() || $('html,body').scrollTop() return scrollTop } /** * 拖拽 */ function dragging() { let isDragging = false; let dragThreshold = 5; // 拖拽阈值,移动超过这个距离才算拖拽 var position = GM_getValue('gtb_pos') || {} var $gtbBox = $('#goTopBottom'); $('#goTopBottom') .off('.gtb') .on({ 'mousedown.gtb': function (el) { if (el.button !== 0) return; // 只在左键点击时处理 var move = true var startX = el.pageX var startY = el.pageY var startLeft = $gtbBox.offset().left var startTop = $gtbBox.offset().top var movedDistance = 0 $doc.on({ 'mousemove.gtb': function (docEl) { if (move) { var deltaX = docEl.pageX - startX var deltaY = docEl.pageY - startY movedDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY) // 如果移动距离超过阈值,则认为是拖拽 if (movedDistance > dragThreshold) { isDragging = true; $gtbBox.offset({ left: startLeft + deltaX, top: startTop + deltaY }) } } }, 'mouseup.gtb': function () { move = false $doc.off('.gtb') // 如果是拖拽操作,记录结束时间 if (isDragging) { lastDragEndTime = Date.now(); isDragging = false; } } }) } }); } this.init = function () { CreateStyle() CreateHtml() dragging() GoTB() } } var tbl = new TBLink() tbl.init() })()