// ==UserScript== // @name 手机可拖动折叠回到顶部|修复版 // @namespace http://tampermonkey.net/ // @version 2.0 // @description 可拖动、默认折叠、记忆位置状态、修复坐标BUG、防误触 // @match *://*/* // @grant none // @run-at document-end // @downloadURL https://update.greasyfork.icu/scripts/575535/%E6%89%8B%E6%9C%BA%E5%8F%AF%E6%8B%96%E5%8A%A8%E6%8A%98%E5%8F%A0%E5%9B%9E%E5%88%B0%E9%A1%B6%E9%83%A8%EF%BD%9C%E4%BF%AE%E5%A4%8D%E7%89%88.user.js // @updateURL https://update.greasyfork.icu/scripts/575535/%E6%89%8B%E6%9C%BA%E5%8F%AF%E6%8B%96%E5%8A%A8%E6%8A%98%E5%8F%A0%E5%9B%9E%E5%88%B0%E9%A1%B6%E9%83%A8%EF%BD%9C%E4%BF%AE%E5%A4%8D%E7%89%88.meta.js // ==/UserScript== (function() { 'use strict'; const STORAGE_KEY = "back_top_float_data"; // 防重复注入 if (document.querySelector("#dragFloatWrap")) return; // ===== 修复1:增加JSON解析容错 try/catch ===== let saveData; try { const local = localStorage.getItem(STORAGE_KEY); saveData = local ? JSON.parse(local) : null; } catch (e) { saveData = null; } // 默认配置 const defaultData = { right: 16, bottom: 100, isFold: true }; saveData = Object.assign({}, defaultData, saveData); // 外层容器 const wrap = document.createElement("div"); wrap.id = "dragFloatWrap"; wrap.style.cssText = ` position: fixed; right: ${saveData.right}px; bottom: ${saveData.bottom}px; z-index: 999999; user-select: none; touch-action: none; box-sizing: border-box; `; // 折叠开关按钮 const foldBtn = document.createElement("div"); foldBtn.style.cssText = ` width: 40px; height: 40px; line-height: 40px; text-align: center; background: #1677ff; color: #fff; border-radius: 50%; font-size: 18px; box-shadow: 0 2px 8px rgba(0,0,0,0.2); box-sizing: border-box; `; // 功能区容器 const contentBox = document.createElement("div"); contentBox.style.cssText = ` position: absolute; bottom: 50px; right: 0; display: none; box-sizing: border-box; `; // 回到顶部按钮 const topBtn = document.createElement("div"); topBtn.style.cssText = ` width: 46px; height: 46px; line-height: 46px; text-align: center; background: #22c55e; color: #fff; border-radius: 50%; font-size: 20px; margin-bottom: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.2); box-sizing: border-box; `; topBtn.innerText = "↑"; // 结构挂载 contentBox.appendChild(topBtn); wrap.appendChild(contentBox); wrap.appendChild(foldBtn); document.body.appendChild(wrap); // 初始化折叠状态 function initFoldState() { if (saveData.isFold) { contentBox.style.display = "none"; foldBtn.innerText = "☰"; } else { contentBox.style.display = "block"; foldBtn.innerText = "✕"; } } initFoldState(); // 折叠切换 + 保存状态 foldBtn.addEventListener("click", (e) => { e.stopPropagation(); saveData.isFold = !saveData.isFold; initFoldState(); localStorage.setItem(STORAGE_KEY, JSON.stringify(saveData)); }); // 回到顶部 topBtn.addEventListener("click", (e) => { e.stopPropagation(); window.scrollTo({ top: 0, behavior: "smooth" }); }); // ===== 修复2:标准坐标 + 拖动阈值防误触 ===== let isDrag = false; let startX = 0, startY = 0; let initRight = 0, initBottom = 0; const MOVE_THRESHOLD = 8; // 移动阈值,小于则判定为点击 wrap.addEventListener("touchstart", (e) => { const rect = wrap.getBoundingClientRect(); startX = e.touches[0].clientX; startY = e.touches[0].clientY; initRight = rect.right; initBottom = document.documentElement.clientHeight - rect.bottom; isDrag = false; }); wrap.addEventListener("touchmove", (e) => { const dx = startX - e.touches[0].clientX; const dy = startY - e.touches[0].clientY; // 超过阈值判定为拖动 if (Math.abs(dx) > MOVE_THRESHOLD || Math.abs(dy) > MOVE_THRESHOLD) { isDrag = true; } wrap.style.right = `${initRight + dx}px`; wrap.style.bottom = `${initBottom - dy}px`; }); wrap.addEventListener("touchend", () => { // 拖动结束才保存位置 if (isDrag) { const rect = wrap.getBoundingClientRect(); saveData.right = document.documentElement.clientWidth - rect.right; saveData.bottom = document.documentElement.clientHeight - rect.bottom; localStorage.setItem(STORAGE_KEY, JSON.stringify(saveData)); } isDrag = false; }); })();