利用GPT实现油猴脚本—网页滚动(优化版)

在浏览网页的时候,发现有的网页没有直达最前这样的功能,所有心血来潮利用ChatGPT写了一个油猴脚本以实现此功能,在网站上出现一个可以自由拖动的滑块。

声明:引用或二创需注明出处。


如图:

点击即可直达当前网页最前、中间、最后。

可以任意在网页上推动,点击小齿轮有简单的设置。

感觉可以在优化一下,直接发布脚本了。


脚本在此,可以复制自己用哟:

javascript 复制代码
// ==UserScript==
// @name         滚动助手(优化版)
// @namespace    https://github.com/yourname/scroll-helper
// @version      1.0
// @description  支持快捷滚动、自定义热键、图标拖动、暗色模式、图形化设置中心,适配所有网页
// @author       GPT、依旧天真无邪
// @match        *://*/*
// @require      https://unpkg.com/sweetalert2@10.16.6/dist/sweetalert2.all.min.js
// @grant        none
// ==/UserScript==

(function () {
  'use strict';

  const defaultConfig = {
    scrollKeys: { top: 'ArrowUp', bottom: 'ArrowDown' },
    autoShow: true,
    iconSize: 18,
    iconGap: 8,
    borderRadius: 12,
    panelOpacity: 60,
    iconPos: { right: 30, bottom: 100 },
    darkMode: false,
    keyEnabled: true
  };
  const storageKey = 'ScrollHelperConfig';
  const config = Object.assign({}, defaultConfig, JSON.parse(localStorage.getItem(storageKey) || '{}'));
  const isDark = config.darkMode || window.matchMedia('(prefers-color-scheme: dark)').matches;

  const Util = {
    saveConfig() {
      localStorage.setItem(storageKey, JSON.stringify(config));
    },
    createBtn(id, label, title, onClick) {
      const btn = document.createElement('button');
      btn.id = id;
      btn.textContent = label;
      btn.title = title;
      Object.assign(btn.style, {
        all: 'unset',
        fontSize: `${config.iconSize}px`,
        padding: '6px',
        borderRadius: `${config.borderRadius}px`,
        background: isDark ? '#444' : '#007BFF',
        color: '#fff',
        cursor: 'pointer',
        boxShadow: '0 1px 4px rgba(0,0,0,0.2)',
        textAlign: 'center',
        transition: 'transform 0.2s'
      });
      btn.onmouseover = () => btn.style.transform = 'scale(1.1)';
      btn.onmouseout = () => btn.style.transform = 'scale(1.0)';
      btn.onmousedown = () => btn.style.transform = 'scale(0.9)';
      btn.onmouseup = () => btn.style.transform = 'scale(1.1)';
      btn.onclick = onClick;
      return btn;
    },
    limitToViewport(pos) {
      const w = window.innerWidth;
      const h = window.innerHeight;
      pos.right = Math.min(Math.max(0, pos.right), w - 50);
      pos.bottom = Math.min(Math.max(0, pos.bottom), h - 50);
      return pos;
    }
  };

  const UI = {
    panel: null,
    createPanel() {
      const panel = document.createElement('div');
      panel.id = 'scroll-helper-panel';
      Object.assign(panel.style, {
        position: 'fixed',
        right: `${config.iconPos.right}px`,
        bottom: `${config.iconPos.bottom}px`,
        display: 'flex',
        flexDirection: 'column',
        gap: `${config.iconGap}px`,
        zIndex: 99999,
        opacity: config.panelOpacity / 100,
        cursor: 'move'
      });
      this.panel = panel;

      const buttons = [
        Util.createBtn('scroll-top', '⬆️', '返回顶部', () => window.scrollTo({ top: 0, behavior: 'smooth' })),
        Util.createBtn('scroll-mid', '↕️', '滚动中部', () => window.scrollTo({ top: (document.body.scrollHeight - window.innerHeight) / 2, behavior: 'smooth' })),
        Util.createBtn('scroll-bottom', '⬇️', '滚动到底', () => window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' })),
        Util.createBtn('scroll-settings', '⚙️', '设置中心', UI.openSettings)
      ];
      buttons.forEach(btn => panel.appendChild(btn));
      document.body.appendChild(panel);
      this.enableDrag();
    },
    enableDrag() {
      let isDragging = false, startX, startY;
      this.panel.addEventListener('mousedown', (e) => {
        isDragging = true;
        startX = e.clientX;
        startY = e.clientY;
        e.preventDefault();
      });
      window.addEventListener('mousemove', (e) => {
        if (!isDragging) return;
        const dx = e.clientX - startX;
        const dy = e.clientY - startY;
        config.iconPos.right -= dx;
        config.iconPos.bottom -= dy;
        Util.limitToViewport(config.iconPos);
        this.panel.style.right = `${config.iconPos.right}px`;
        this.panel.style.bottom = `${config.iconPos.bottom}px`;
        startX = e.clientX;
        startY = e.clientY;
      });
      window.addEventListener('mouseup', () => {
        if (isDragging) {
          isDragging = false;
          Util.saveConfig();
        }
      });
    },
    openSettings() {
      const html = `
        <div style="text-align:left">
          <label>图标大小:
            <input type="number" id="set-iconSize" value="${config.iconSize}" style="width:60px">
          </label><br><br>
          <label>圆角半径:
            <input type="number" id="set-radius" value="${config.borderRadius}" style="width:60px">
          </label><br><br>
          <label>透明度(%):
            <input type="number" id="set-opacity" value="${config.panelOpacity}" style="width:60px">
          </label><br><br>
          <label><input type="checkbox" id="set-autoShow" ${config.autoShow ? 'checked' : ''}> 自动显示滚动按钮</label><br><br>
          <label><input type="checkbox" id="set-keyEnabled" ${config.keyEnabled ? 'checked' : ''}> 启用快捷键 Ctrl+↑↓</label><br><br>
          <label><input type="checkbox" id="set-darkMode" ${config.darkMode ? 'checked' : ''}> 暗色模式</label>
        </div>`;
      Swal.fire({
        title: '滚动助手设置',
        html,
        confirmButtonText: '保存设置',
        showCancelButton: true,
        preConfirm: () => {
          config.iconSize = parseInt(document.getElementById('set-iconSize').value);
          config.borderRadius = parseInt(document.getElementById('set-radius').value);
          config.panelOpacity = parseInt(document.getElementById('set-opacity').value);
          config.autoShow = document.getElementById('set-autoShow').checked;
          config.keyEnabled = document.getElementById('set-keyEnabled').checked;
          config.darkMode = document.getElementById('set-darkMode').checked;
          Util.saveConfig();
        }
      }).then(res => {
        if (res.isConfirmed) {
          location.reload(); // 刷新页面以应用新设置
        }
      });
    },
    handleScrollDisplay() {
      if (!config.autoShow) {
        this.panel.style.display = 'flex';
        return;
      }
      window.addEventListener('scroll', () => {
        if (window.scrollY > 200) {
          this.panel.style.display = 'flex';
        } else {
          this.panel.style.display = 'none';
        }
      });
    }
  };

  const Shortcut = {
    init() {
      if (!config.keyEnabled) return;
      document.addEventListener('keydown', (e) => {
        if (e.ctrlKey && e.key === config.scrollKeys.top) {
          window.scrollTo({ top: 0, behavior: 'smooth' });
        }
        if (e.ctrlKey && e.key === config.scrollKeys.bottom) {
          window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
        }
      });
    }
  };

  function init() {
    UI.createPanel();
    UI.handleScrollDisplay();
    Shortcut.init();
  }

  if (document.readyState === 'complete' || document.body) {
    init();
  } else {
    window.addEventListener('DOMContentLoaded', init);
  }

})();
相关推荐
智慧地球(AI·Earth)1 天前
智能体版中科院学术GPT上线内测!AI与科研的深度碰撞
人工智能·gpt·科研助手·学术智能体
workflower1 天前
将图片中的图形转换为可编辑的 PPT 图形
java·开发语言·tomcat·powerpoint·个人开发·结对编程
liu****2 天前
负载均衡式的在线OJ项目编写(六)
运维·c++·负载均衡·个人开发
C++chaofan2 天前
项目中为AI添加对话记忆
java·数据结构·人工智能·redis·缓存·个人开发·caffeine
武子康3 天前
AI-调查研究-90-具身智能 机器人数据采集与通信中间件全面解析:ROS/ROS2、LCM 与工业总线对比
人工智能·ai·中间件·机器人·职场发展·个人开发·具身智能
新知图书3 天前
大模型架构之GPT、LLaMA与PaLM模型
人工智能·gpt·语言模型·大模型应用开发·大模型应用
KKKlucifer3 天前
GPT-4 赋能恶意软件 GPT-MalPro:国内首现动态生成规避检测的勒索程序技术深度解析
大数据·人工智能·gpt
LinkTime_Cloud3 天前
OpenAI 陷“GPT门”风波,付费用户遭遇模型偷换与性能降级
人工智能·gpt
LETTER•3 天前
从GPT-1到GPT-3:生成式预训练语言模型的演进之路
gpt·深度学习·语言模型·自然语言处理
七牛云行业应用4 天前
GPT-5 撼动量子计算:AI 在科研领域的颠覆性应用
人工智能·gpt·量子计算·gpt5