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