Auto Scroll Mouse

No mousewheel? No problem! This script will scroll the page if you place your mouse near the top or bottom of the window and wiggle it.

目前为 2018-12-25 提交的版本。查看 最新版本

// ==UserScript==
// @name          Auto Scroll Mouse
// @namespace     http://www.marcbelmont.com
// @description   No mousewheel?  No problem!  This script will scroll the page if you place your mouse near the top or bottom of the window and wiggle it.
// @version       2.1.7
// @license       ISC
// @include       http://*/*
// @include       https://*/*
// @grant         GM_addStyle
// @run-at        document-start
// ==/UserScript==

// Originally "Auto Scroll!" by Marc Belmont on userscripts.org
// Tweaked by joeytwiddle

// TODO: Do not scroll after/during a mousedown (so it won't interfere when dragging/selecting)
// BUG: Does not trigger when mouse is over an iframe (window does not receive the mousemove event)
//      We could solve this by listening for mousemove events on the region divs instead of on the document.
//      But that could be more disruptive, as it prevents events from reaching the window like they normally would.

//////////////////////
// Constants        //
//////////////////////

// Which key should be held to enable scrolling.  Possible values are 0 | 1
// Enable more than one to require a combination be held.
var ONLY_WHEN_HOLDING_SHIFT = 0;
var ONLY_WHEN_HOLDING_CTRL = 0;
var ONLY_WHEN_HOLDING_ALT = 0;

var NOSCROLL_PERCENT = 80; // Area in the middle of the page where there won't be scrolling
var SCROLLSTEP = 5; // Scrolling speed
var ONLYLEFTRIGHT = 1; // Scrolling will happen only when you move left or right in the top or bottom areas. Possible values are 0 | 1
var ONLYLEFTRIGHT_MOUSESPEED = 1.5; // Acceleration
var ONLYLEFTRIGHT_DONTSCROLL = 100; // if no event for too long, no scrolling
var DELAY_TIME = 5; // This tries to reduce the number of scroll operations, to reduce load on the browser
var SHOW_ACTIVE_REGION = 1;

//////////////////////
// Some Code        //
//////////////////////

var _mX = 0;
var _mXOld = 0;
var _mYOld = 0;
var _mY = 0;
var _go = 0;
var _mNow = new Date();
var _mThen = new Date();

// 2. scroll the window
function ScrollWindow() {
  // don't scroll if we're in the middle of the page
  var end = ((_mY - window.pageYOffset) - window.innerHeight/2);
  if (Math.abs(end) < window.innerHeight*NOSCROLL_PERCENT/200) {
    return;
  }
  /* var down = (_mY - window.pageYOffset) / window.innerHeight;
  if (Math.abs(down - 0.5)*2 < NOSCROLL_PERCENT/100) {
    return;
  } */

  // if ONLYLEFTRIGHT is on, scroll only when you move left or right,
  if (ONLYLEFTRIGHT && (Math.abs(_mY - _mYOld) > 2)) {
    return;
  }
  // if you want scrolling, mouse have to go start moving slowly
  if (Math.abs(_mY - _mYOld) < 7 && Math.abs(_mX - _mXOld) < 7)
    _go = 1;


  // scroll the page
  var way = end > 0 ? 1 : -1;
  var val = SCROLLSTEP;
  if (ONLYLEFTRIGHT) {
    if (_go) {
      val = Math.pow(Math.abs(_mX - _mXOld), ONLYLEFTRIGHT_MOUSESPEED);
    } else {
      val = 0;
    }
  }
  if (val != 0) {
    window.scrollTo(window.pageXOffset, window.pageYOffset + val*way);
  }
  if (ONLYLEFTRIGHT && SHOW_ACTIVE_REGION && val != 0) {
    if (end > 0) {
      regionUI.showBottomRegion();
    } else {
      regionUI.showTopRegion();
    }
  }
}

function maybe(scrollWindow) {
  var timer;
  return function(){
    if (!timer) {
      timer = setTimeout(function(){
        timer = null;
        scrollWindow();
        _mXOld = _mX;
        _mYOld = _mY;
        _mThen = _mNow;
      }, DELAY_TIME);
    }
  };
}

var maybeScrollWindow = maybe(ScrollWindow);

// 1. Catch mouse movement
document.addEventListener('mousemove', mousemove, true);
function mousemove(e)
{
  // get mouse pos and the date
  if (!e)
    e = window.event || window.Event;
  if('undefined'!=typeof e.pageX) {
    _mX = e.pageX;
    _mY = e.pageY;
  } else {
    _mX = e.clientX + document.body.scrollLeft;
    _mY = e.clientY + document.body.scrollTop;
  }
  _mNow = Date.now();

  // Hack to avoid unwanted scrolling when the mouse enters a window
  // if no event for too long, no scrolling
  if (_mNow - _mThen > ONLYLEFTRIGHT_DONTSCROLL)
    _go = 0;

  if (ONLY_WHEN_HOLDING_SHIFT && !e.shiftKey) return;
  if (ONLY_WHEN_HOLDING_CTRL && !e.ctrlKey) return;
  if (ONLY_WHEN_HOLDING_ALT && !e.altKey) return;

  // Scroll the window
  maybeScrollWindow();
}

var regionUI = (function() {
  var topRegion = null;
  var bottomRegion = null;

  function ensureRegionsExist() {
    if (!bottomRegion) {
      topRegion = document.createElement('div');
      topRegion.className = 'ASM_region';
      topRegion.style.top = 0;
      topRegion.style.width = '100%';
      topRegion.style.height = (100 - NOSCROLL_PERCENT) / 2 + '%';
      document.body.appendChild(topRegion);
      bottomRegion = document.createElement('div');
      bottomRegion.className = 'ASM_region';
      bottomRegion.style.bottom = 0;
      bottomRegion.style.width = '100%';
      bottomRegion.style.height = (100 - NOSCROLL_PERCENT) / 2 + '%';
      document.body.appendChild(bottomRegion);
      GM_addStyle(`
        .ASM_region {
          position: fixed;
          z-index: 99999999;
          background: #09c4;
          pointer-events: none;
          transition: opacity 1s 0.5s;
          opacity: 0;
        }
        .ASM_region.ASM_show {
          display: block;
          transition: opacity 0.5s; /* See the setTimeout below */
          opacity: 1;
        }
      `);
    }
  }

  function showRegion(regionElement) {
    regionElement.classList.add('ASM_show');
    //regionElement.offsetWidth;
    // We need to wait long enough for the new state to fade in before we remove the class.
    setTimeout(() => {
      regionElement.classList.remove('ASM_show');
    }, 500);
  }

  function showTopRegion() {
    ensureRegionsExist();
    showRegion(topRegion);
  }

  function showBottomRegion() {
    ensureRegionsExist();
    showRegion(bottomRegion);
  }

  return {
    ensureRegionsExist: ensureRegionsExist,
    showTopRegion: showTopRegion,
    showBottomRegion: showBottomRegion,
  };
}());

if (SHOW_ACTIVE_REGION) {
  // It's good to create them at the start, otherwise the first animation won't fade in (because the region will be given the 'ASM_show' class on the same tick that it was created).
  document.addEventListener('DOMContentLoaded', function() {
    regionUI.ensureRegionsExist();
  });
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址