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

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

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


如图:

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

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

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


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

javascript 复制代码
// ==UserScript==
// @name         滚动助手(优化版)
// @namespace    https://github.com/yourname/scroll-helper
// @version      1.0
// @description  支持快捷滚动、自定义热键、图标拖动、暗色模式、图形化设置中心,适配所有网页
// @author       GPT、依旧天真无邪
// @match        *://*/*
// @require      https://unpkg.com/[email protected]/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);
  }

})();
相关推荐
偷偷折个角︿21 小时前
GPT官网/官方入口在哪?国内如何流畅使用ChatGPT?最新镜像站与使用指南
人工智能·gpt·ai·chatgpt
soso(找工作版1 天前
【链表扫盲】FROM GPT
python·gpt·链表
kkai人工智能2 天前
DeepSeek的100个应用场景
人工智能·gpt·学习·chatgpt
TGITCIC3 天前
深夜突发:OpenAI紧急修复GPT-4o“献媚”问题
人工智能·gpt·大模型·openai·agi·gpt4o·人工智能趋势
china10003 天前
大模型系列(三)--- GPT1论文研读
人工智能·gpt
武子康4 天前
大语言模型 06 - 从0开始训练GPT 0.25B参数量 - MiniMind 实机配置 GPT训练基本流程概念
人工智能·gpt·ai·语言模型·自然语言处理
溪饱鱼4 天前
Nuxt3还能用吗?
前端·个人开发·seo
江鸟19985 天前
AI日报 · 2025年5月03日|Perplexity 集成 WhatsApp,苹果传与 Anthropic 合作开发 Xcode
人工智能·gpt·macos·大模型·agent·xcode·智能体
蚂蚁数据AntData5 天前
DB-GPT V0.7.1 版本更新:支持多模态模型、支持 Qwen3 系列,GLM4 系列模型 、支持Oracle数据库等
大数据·数据库·gpt·oracle·架构