Greasy Fork 还支持 简体中文。

返回顶部和底部-美化版

一个很漂亮的可返回顶部或底部的可拖拽的按钮,支持忽略网站和右键菜单

目前為 2025-04-08 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         返回顶部和底部-美化版
// @version      1.1.0
// @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/
// ==/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 = `
      <div id="goTopBottom" style="display:flex;justify-content: center;align-items: center;width:50px;height:100px;">
                      <span class="t-btn gotop" title="返回顶部" style="opacity: 0;">
                        <svg t="1681901274619" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3044" id="mx_n_1681901274619" width="22" height="22"><path d="M199.36 572.768a31.904 31.904 0 0 0 22.624-9.376l294.144-294.144 285.728 285.728a31.968 31.968 0 1 0 45.248-45.248l-308.352-308.352a32 32 0 0 0-45.28 0l-316.768 316.768a31.968 31.968 0 0 0 22.656 54.624z" p-id="3045" fill="#ffffff"></path><path d="M538.784 457.376a32 32 0 0 0-45.28 0l-316.768 316.768a31.968 31.968 0 1 0 45.248 45.248l294.144-294.144 285.728 285.728a31.968 31.968 0 1 0 45.248-45.248l-308.32-308.352z" p-id="3046" fill="#ffffff"></path></svg>
                      </span>

                      <span class="t-btn bottom" title="返回底部" style="opacity: 0;">
                         <svg t="1681901383895" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4902" id="mx_n_1681901383896" width="22" height="22"><path d="M493.504 558.144a31.904 31.904 0 0 0 45.28 0l308.352-308.352a31.968 31.968 0 1 0-45.248-45.248l-285.728 285.728-294.176-294.144a31.968 31.968 0 1 0-45.248 45.248l316.768 316.768z" p-id="4903" fill="#ffffff"></path><path d="M801.888 460.576l-285.728 285.728-294.144-294.144a31.968 31.968 0 1 0-45.248 45.248l316.768 316.768a31.904 31.904 0 0 0 45.28 0l308.352-308.352a32 32 0 1 0-45.28-45.248z" p-id="4904" fill="#ffffff"></path></svg>
                      </span>
                </div>
`
      $('html body').append(html)

      // 添加右键菜单
      $('#goTopBottom').on('contextmenu', showContextMenu);
    }

    // 创建右键菜单
    var createContextMenu = function() {
      var menu = $('<div id="gtb-context-menu"></div>').css({
        position: 'absolute',
        background: 'white',
        border: '1px solid #ccc',
        borderRadius: '5px',
        boxShadow: '0 2px 5px rgba(0,0,0,0.2)',
        padding: '5px 0',
        zIndex: 10000,
        display: 'none'
      });

      // 创建关闭选项
      var closeOption = $('<div>关闭按钮</div>').css({
        padding: '8px 15px',
        cursor: 'pointer'
      }).hover(
        function() { $(this).css('backgroundColor', '#f5f5f5'); },
        function() { $(this).css('backgroundColor', 'white'); }
      ).click(hideScrollButtons);

      // 创建忽略网站选项
      var ignoreOption = $('<div>忽略此网站</div>').css({
        padding: '8px 15px',
        cursor: 'pointer'
      }).hover(
        function() { $(this).css('backgroundColor', '#f5f5f5'); },
        function() { $(this).css('backgroundColor', 'white'); }
      ).click(ignoreCurrentSite);

      menu.append(closeOption).append(ignoreOption);
      $('body').append(menu);

      return menu;
    }

    // 显示右键菜单
    var showContextMenu = function(e) {
      e.preventDefault();

      var menu = $('#gtb-context-menu');
      if (menu.length === 0) {
        menu = createContextMenu();
      }

      // 设置菜单位置
      menu.css({
        left: e.clientX + 'px',
        top: e.clientY + 'px',
        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 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').click(function () {
        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 justDragged = 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) {
                    justDragged = true
                    $gtbBox.offset({
                      left: startLeft + deltaX,
                      top: startTop + deltaY
                    })
                  }
                }
              },
              'mouseup.gtb': function () {
                move = false
                $doc.off('.gtb')

                // 如果是拖拽操作,延迟重置justDragged标志
                if (justDragged) {
                  setTimeout(function() {
                    justDragged = false
                  }, 300) // 300ms后重置,防止误触
                }
              }
            })
          }
        });

      // 修改点击事件,防止拖拽后误触发点击
      $('#goTopBottom span').on('click', function(e) {
        if (justDragged) {
          e.preventDefault()
          e.stopPropagation()
          return false
        }
      })
    }
    this.init = function () {
      CreateStyle()
      CreateHtml()
      dragging()
      GoTB()
    }
  }
  var tbl = new TBLink()
  tbl.init()
})()