MomentumScrolling

Add drag-scrolling and momentum.

目前为 2017-06-12 提交的版本。查看 最新版本

// ==UserScript==
// @name        MomentumScrolling
// @namespace   http://pussy/MomentumScrolling
// @include     *
// @version     1.6
// @grant       none
// @description Add drag-scrolling and momentum.
// ==/UserScript==
(function () {
  'use strict';
  // Settings -------------------------------------------------------
  // Scroll-speed
  var INERTIA = 0.97;
  var ACCEL_ON_MOUSEUP = 1.7;
  var MIN_SPEED = 0.005;
  // Interface
  var DRAG_BUTTON = 0; // 0:LeftButton, 1:MiddleButton, 2:RightButton
  var DRAG_TIMEOUT = 500; // [ms] (cancel on Long tap)
  var DISABLE_WHEN_TEXT_SELECTED = false;
  var DISABLE_TAGNAMES = [
    'INPUT',
    'TEXTAREA'
  ];
  // ----------------------------------------------------------------
  var enabled = false;
  var dragging = false;
  var target = null;
  var mouseX = 0;
  var mouseY = 0;
  var momentX = 0;
  var momentY = 0;
  var timeoutIds = {
  };
  var timeout = function (id, f, ms) {
    if (timeoutIds[id]) clearTimeout(timeoutIds[id]);
    if (f && ms) {
      timeoutIds[id] = setTimeout(f, ms);
    } else {
      timeoutIds[id] = null;
    }
  };
  var scrollTarget = function () {
    if (target.scrollBy) {
      target.scrollBy(momentX, momentY);
    } else {
      target.scrollLeft += momentX;
      target.scrollTop += momentY;
    }
  };
  var momentScroll = function (e) {
    if (Math.abs(momentX) < MIN_SPEED && Math.abs(momentY) < MIN_SPEED) return;
    scrollTarget();
    momentX *= INERTIA;
    momentY *= INERTIA;
    setTimeout(momentScroll, 16); // 60fps
  };
  var dragEnd = function (e) {
    if (!dragging) return;
    dragging = false;
    document.body.classList.remove('drag-momental-scroll--dragging');
    timeout('resetMoment', null);
    momentX *= ACCEL_ON_MOUSEUP;
    momentY *= ACCEL_ON_MOUSEUP;
    setTimeout(momentScroll, 20);
  };
  var toggle = function (e) {
    enabled = arguments ? e : !enabled;
    if (enabled) {
      document.body.classList.add('drag-momental-scroll--enabled');
    } else {
      dragEnd();
      document.body.classList.remove('drag-momental-scroll--enabled');
    }
  };
  var findTarget = function (elm) {
    while (elm) {
      if (elm.style && (elm.style.overflow == 'auto' || elm.style.overflow == 'scroll')) return elm;
      elm = elm.parentNode;
    }
    return window;
  };
  window.addEventListener('mousedown', function (e) {
    if (!enabled) return;
    if (e.button != DRAG_BUTTON) return;
    if (DISABLE_TAGNAMES.includes(e.target.tagName)) return;
    target = findTarget(e.target);
    mouseX = e.clientX;
    mouseY = e.clientY;
    momentX = 0;
    momentY = 0;
    dragging = true;
    document.body.classList.add('drag-momental-scroll--dragging');
    timeout('cancel', function () {
      toggle(false);
    }, DRAG_TIMEOUT);
  });
  window.addEventListener('mouseup', function (e) {
    dragEnd(e);
    timeout('cancel', null);
    toggle(true);
  });
  window.addEventListener('mousemove', function (e) {
    if (!enabled) return;
    if (!dragging) return;
    if (DISABLE_WHEN_TEXT_SELECTED && window.getSelection().toString()) {
      toggle(false);
      return;
    }
    momentX = mouseX - e.clientX;
    momentY = mouseY - e.clientY;
    if (momentX >= 1 || momentY >= 1) {
      timeout('cancel', null);
    }
    mouseX = e.clientX;
    mouseY = e.clientY;
    scrollTarget();
    timeout('resetMoment', function (e) {
      momentX = 0;
      momentY = 0;
    }, 100);
  });
  document.getElementsByTagName('head') [0].appendChild(document.createElement('style'));
  var ss = document.styleSheets[document.styleSheets.length - 1];
  ss.insertRule('.drag-momental-scroll--enabled { cursor: default; }', 0);
  ss.insertRule('.drag-momental-scroll--dragging { cursor: grabbing !important;}', 0);
  toggle(true);
}) ();

QingJ © 2025

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