// ==UserScript== // @name 滚动到底部和顶部 // @namespace http://tampermonkey.net/ // @version 0.2.0 // @description 实现网页滚动到底部、顶部,处理懒加载内容,支持按钮拖拽,支持忽略当前网站,支持临时关闭当前网站 // @match https://* // @run-at document-body // @grant none // ==/UserScript== (function () { 'use strict'; // 检查是否在iframe中运行 if (window.self !== window.top) { // 在iframe中运行,不执行脚本 return; } // 检查当前网站是否在忽略列表中 const currentHost = window.location.hostname; const ignoredSites = JSON.parse(localStorage.getItem('scrollScript_ignoredSites') || '[]'); // 如果当前网站在忽略列表中,则不执行脚本 if (ignoredSites.includes(currentHost)) { return; } // 全局变量,跟踪是否刚刚完成拖拽操作 let justDragged = false; // 全局变量,存储右键菜单和按钮容器 let contextMenu = null; let buttonContainer = null; // 创建控制按钮容器 function createButtonContainer() { const container = document.createElement('div'); container.style.cssText = ` position: fixed; right: 80px; z-index: 9999; display: flex; flex-direction: column; gap: 10px; opacity: 0.7; transition: opacity 0.3s; `; container.addEventListener('mouseover', () => container.style.opacity = '1'); container.addEventListener('mouseout', () => container.style.opacity = '0.2'); makeDraggable(container); // 添加右键菜单 container.addEventListener('contextmenu', showContextMenu); return container; } // 创建右键菜单 function createContextMenu() { const menu = document.createElement('div'); menu.style.cssText = ` position: absolute; background: white; border: 1px solid #ccc; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.2); padding: 5px 0; z-index: 10000; display: none; `; // 创建关闭选项 const closeOption = document.createElement('div'); closeOption.textContent = '关闭按钮'; closeOption.style.cssText = ` padding: 8px 15px; cursor: pointer; hover: background-color: #f5f5f5; `; closeOption.addEventListener('mouseover', () => closeOption.style.backgroundColor = '#f5f5f5'); closeOption.addEventListener('mouseout', () => closeOption.style.backgroundColor = 'white'); closeOption.addEventListener('click', hideScrollButtons); // 创建忽略网站选项 const ignoreOption = document.createElement('div'); ignoreOption.textContent = '忽略此网站'; ignoreOption.style.cssText = ` padding: 8px 15px; cursor: pointer; hover: background-color: #f5f5f5; `; ignoreOption.addEventListener('mouseover', () => ignoreOption.style.backgroundColor = '#f5f5f5'); ignoreOption.addEventListener('mouseout', () => ignoreOption.style.backgroundColor = 'white'); ignoreOption.addEventListener('click', ignoreCurrentSite); menu.appendChild(closeOption); menu.appendChild(ignoreOption); document.body.appendChild(menu); return menu; } // 显示右键菜单 function showContextMenu(e) { e.preventDefault(); if (!contextMenu) { contextMenu = createContextMenu(); } // 设置菜单位置 contextMenu.style.left = e.clientX + 'px'; contextMenu.style.top = e.clientY + 'px'; contextMenu.style.display = 'block'; // 点击其他区域关闭菜单 const closeMenu = function(e) { contextMenu.style.display = 'none'; document.removeEventListener('click', closeMenu); }; // 延迟添加关闭事件,防止立即触发 setTimeout(() => { document.addEventListener('click', closeMenu); }, 100); } // 隐藏滚动按钮 function hideScrollButtons() { if (buttonContainer) { buttonContainer.style.display = 'none'; } } // 忽略当前网站 function ignoreCurrentSite() { const currentHost = window.location.hostname; let ignoredSites = JSON.parse(localStorage.getItem('scrollScript_ignoredSites') || '[]'); // 添加当前网站到忽略列表 if (!ignoredSites.includes(currentHost)) { ignoredSites.push(currentHost); localStorage.setItem('scrollScript_ignoredSites', JSON.stringify(ignoredSites)); } // 隐藏按钮 hideScrollButtons(); } // 创建控制按钮 function createButton(text, onClick) { const button = document.createElement('button'); button.textContent = text; button.style.cssText = ` width: 70px; height: 35px; padding: 5px; background-color: #4158D0; background-image: linear-gradient(43deg, #4158D0 0%, #C850C0 46%, #FFCC70 100%); color: white; border: none; border-radius: 5px; cursor: pointer; display: flex; justify-content: center; align-items: center; `; // 使用click事件,但检查是否刚刚进行了拖拽 button.addEventListener('click', function(e) { if (justDragged) { e.preventDefault(); e.stopPropagation(); return false; } onClick(e); }); return button; } // 使元素可拖拽 function makeDraggable(element) { let startX = 0, startY = 0; let startPosRight = 0, startPosTop = 0; let isDragging = false; let dragThreshold = 5; // 拖拽阈值,移动超过这个距离才算拖拽 // 确保元素有初始位置 if (!element.style.top) { element.style.top = (window.innerHeight - element.offsetHeight - 150) + 'px'; } element.addEventListener('mousedown', dragMouseDown); function dragMouseDown(e) { // 只在左键点击时处理 if (e.button !== 0) return; e.preventDefault(); // 记录初始位置 startX = e.clientX; startY = e.clientY; startPosRight = parseInt(element.style.right || '0'); startPosTop = parseInt(element.style.top || '0'); isDragging = false; justDragged = false; document.addEventListener('mousemove', elementDrag); document.addEventListener('mouseup', closeDragElement); } function elementDrag(e) { e.preventDefault(); // 计算移动距离 const dx = Math.abs(e.clientX - startX); const dy = Math.abs(e.clientY - startY); // 如果移动距离超过阈值,标记为拖拽 if (!isDragging && (dx > dragThreshold || dy > dragThreshold)) { isDragging = true; } // 直接基于起始位置和当前鼠标位置计算新位置 // 注意:right值需要反向计算(鼠标向右移动,right值减小) if (isDragging) { const moveX = e.clientX - startX; const moveY = e.clientY - startY; element.style.right = (startPosRight - moveX) + 'px'; element.style.top = (startPosTop + moveY) + 'px'; } } function closeDragElement(e) { document.removeEventListener('mousemove', elementDrag); document.removeEventListener('mouseup', closeDragElement); if (isDragging) { justDragged = true; // 重置justDragged状态,给一个足够的时间窗口防止松开后点击 setTimeout(() => { justDragged = false; }, 300); // 防止拖拽结束时触发点击 e.preventDefault(); e.stopPropagation(); } } } // 滚动函数(通用于顶部和底部) function smoothScroll(toTop) { return new Promise((resolve) => { let lastScrollHeight = document.documentElement.scrollHeight; let scrollAttempts = 0; const maxScrollAttempts = 50; // 最大滚动尝试次数 function scroll() { if (toTop) { window.scrollTo({ top: 0, behavior: 'smooth' }); } else { window.scrollTo({ top: document.documentElement.scrollHeight, behavior: 'smooth' }); } scrollAttempts++; setTimeout(() => { const currentScrollHeight = document.documentElement.scrollHeight; if (currentScrollHeight !== lastScrollHeight && scrollAttempts < maxScrollAttempts) { lastScrollHeight = currentScrollHeight; scroll(); } else { resolve(); } }, 500); // 增加等待时间,给平滑滚动和懒加载内容更多时间 } scroll(); }); } // 滚动到顶部 function scrollToTop() { smoothScroll(true); } // 滚动到底部 function scrollToBottom() { smoothScroll(false); } // 创建并添加按钮容器和按钮 buttonContainer = createButtonContainer(); const topButton = createButton('↑ 顶部', scrollToTop); const bottomButton = createButton('↓ 底部', scrollToBottom); buttonContainer.appendChild(topButton); buttonContainer.appendChild(bottomButton); document.body.appendChild(buttonContainer); })();