網站搜尋

javascript - 如何暫時禁用滾動?


我正在使用 scrollTo jQuery 插件,想知道是否有辦法透過 Javascript 暫時禁用 window 元素的滾動?我想禁用滾動的原因是,當 scrollTo 執行動畫時,如果你滾動,它會變得非常醜 ;)

當然,我可以執行 $("body").css("overflow", "hidden");,然後在動畫停止時再把它改回 auto,但如果捲軸仍然可見但不活動,那會更好。

答案#1

scroll 事件無法被取消。但你可以透過 取消 這些互動事件來達成:
滑鼠 & 觸控滾動 以及與滾動相關的 按鈕。

[工作示範]

// left: 37, up: 38, right: 39, down: 40,
// spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
var keys = {37: 1, 38: 1, 39: 1, 40: 1};

function preventDefault(e) {
  e.preventDefault();
}

function preventDefaultForScrollKeys(e) {
  if (keys[e.keyCode]) {
    preventDefault(e);
    return false;
  }
}

// modern Chrome requires { passive: false } when adding event
var supportsPassive = false;
try {
  window.addEventListener("test", null, Object.defineProperty({}, 'passive', {
    get: function () { supportsPassive = true; } 
  }));
} catch(e) {}

var wheelOpt = supportsPassive ? { passive: false } : false;
var wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';

// call this to Disable
function disableScroll() {
  window.addEventListener('DOMMouseScroll', preventDefault, false); // older FF
  window.addEventListener(wheelEvent, preventDefault, wheelOpt); // modern desktop
  window.addEventListener('touchmove', preventDefault, wheelOpt); // mobile
  window.addEventListener('keydown', preventDefaultForScrollKeys, false);
}

// call this to Enable
function enableScroll() {
  window.removeEventListener('DOMMouseScroll', preventDefault, false);
  window.removeEventListener(wheelEvent, preventDefault, wheelOpt); 
  window.removeEventListener('touchmove', preventDefault, wheelOpt);
  window.removeEventListener('keydown', preventDefaultForScrollKeys, false);
}

更新:修復了使用被動監聽器的 Chrome 桌面版和現代行動瀏覽器

答案#2

只需給 body 添加一個類別即可:

.stop-scrolling {
  height: 100%;
  overflow: hidden;
}

添加該類別,然後在您想要重新啟用滾動時將其移除,已在 IE、FF、Safari 和 Chrome 中測試過。

$('body').addClass('stop-scrolling')

答案#3

這裡有一個非常基本的方法來做這件事:

window.onscroll = function () { window.scrollTo(0, 0); };

在 IE6 上有點跳動。

答案#4

以下解決方案是基本的,但純粹使用 JavaScript(不使用 jQuery):

function disableScrolling(){
    var x=window.scrollX;
    var y=window.scrollY;
    window.onscroll=function(){window.scrollTo(x, y);};
}

function enableScrolling(){
    window.onscroll=function(){};
}

答案#5

很抱歉回覆一個舊帖,但我正在尋找解決方案時發現了這個問題。

針對這個問題有許多解決方法可以仍然顯示滾動條,例如給容器設定 100% 高度並加上 overflow-y: scroll 樣式。

在我的情況下,我只是創建了一個帶有滾動條的 div,並在 body 上添加 overflow: hidden 時顯示它:

function disableScroll() {
    document.getElementById('scrollbar').style.display = 'block';
    document.body.style.overflow = 'hidden';
}

滾動條元素必須有這些樣式:

overflow-y: scroll; top: 0; right: 0; display: none; height: 100%; position: fixed;

這顯示了一個灰色的捲軸,希望能幫助未來的訪客。

答案#6

這個解決方案在禁用滾動時將保持當前的滾動位置,不像有些方案會將用戶跳回到頂部。

它是基於 galambalazs 的回答,但增加了對觸控設備的支持,並重構為帶有 jQuery 插件包裝的單一物件。

這裡是示範。

在 GitHub 這裡。

/**
 * $.disablescroll
 * Author: Josh Harrison - aloof.co
 *
 * Disables scroll events from mousewheels, touchmoves and keypresses.
 * Use while jQuery is animating the scroll position for a guaranteed super-smooth ride!
 */

;(function($) {

    "use strict";

    var instance, proto;

    function UserScrollDisabler($container, options) {
        // spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
        // left: 37, up: 38, right: 39, down: 40
        this.opts = $.extend({
            handleKeys : true,
            scrollEventKeys : [32, 33, 34, 35, 36, 37, 38, 39, 40]
        }, options);

        this.$container = $container;
        this.$document = $(document);
        this.lockToScrollPos = [0, 0];

        this.disable();
    }

    proto = UserScrollDisabler.prototype;

    proto.disable = function() {
        var t = this;

        t.lockToScrollPos = [
            t.$container.scrollLeft(),
            t.$container.scrollTop()
        ];

        t.$container.on(
            "mousewheel.disablescroll DOMMouseScroll.disablescroll touchmove.disablescroll",
            t._handleWheel
        );

        t.$container.on("scroll.disablescroll", function() {
            t._handleScrollbar.call(t);
        });

        if(t.opts.handleKeys) {
            t.$document.on("keydown.disablescroll", function(event) {
                t._handleKeydown.call(t, event);
            });
        }
    };

    proto.undo = function() {
        var t = this;
        t.$container.off(".disablescroll");
        if(t.opts.handleKeys) {
            t.$document.off(".disablescroll");
        }
    };

    proto._handleWheel = function(event) {
        event.preventDefault();
    };

    proto._handleScrollbar = function() {
        this.$container.scrollLeft(this.lockToScrollPos[0]);
        this.$container.scrollTop(this.lockToScrollPos[1]);
    };

    proto._handleKeydown = function(event) {
        for (var i = 0; i < this.opts.scrollEventKeys.length; i++) {
            if (event.keyCode === this.opts.scrollEventKeys[i]) {
                event.preventDefault();
                return;
            }
        }
    };


    // Plugin wrapper for object
    $.fn.disablescroll = function(method) {

        // If calling for the first time, instantiate the object and save
        // reference. The plugin can therefore only be instantiated once per
        // page. You can pass options object in through the method parameter.
        if( ! instance && (typeof method === "object" || ! method)) {
            instance = new UserScrollDisabler(this, method);
        }

        // Instance already created, and a method is being explicitly called,
        // e.g. .disablescroll('undo');
        else if(instance && instance[method]) {
            instance[method].call(instance);
        }

    };

    // Global access
    window.UserScrollDisabler = UserScrollDisabler;

})(jQuery);

答案#7

var winX = null;
var winY = null;

window.addEventListener('scroll', function () {
    if (winX !== null && winY !== null) {
        window.scrollTo(winX, winY);
    }
});

function disableWindowScroll() {
    winX = window.scrollX;
    winY = window.scrollY;
}

function enableWindowScroll() {
    winX = null;
    winY = null;
}