Javascript 如何暂时禁用滚动?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4770025/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:00:18  来源:igfitidea点击:

How to disable scrolling temporarily?

javascriptjqueryscroll

提问by Olivier Lalonde

I'm using the scrollTo jQuery plugin and would like to know if it is somehow possible to temporarily disable scrolling on the window element through Javascript? The reason I'd like to disable scrolling is that when you scroll while scrollTo is animating, it gets really ugly ;)

我正在使用 scrollTo jQuery 插件,想知道是否可以通过 Javascript 暂时禁用窗口元素上的滚动?我想禁用滚动的原因是,当您在 scrollTo 动画时滚动时,它变得非常难看 ;)

Of course, I could do a $("body").css("overflow", "hidden");and then put it back to auto when the animation stops, but it would be better if the scrollbar was still visible but inactive.

当然,我可以做 a$("body").css("overflow", "hidden");然后在动画停止时将它放回 auto ,但如果滚动条仍然可见但不活动会更好。

回答by gblazex

The scrollevent cannot be canceled. But you can do it by cancelingthese interaction events:
Mouse&Touch scrolland Buttonsassociated with scrolling.

scroll事件无法取消。但是您可以通过取消这些交互事件来实现:
鼠标触摸滚动以及与滚动相关的按钮

[Working demo]

[工作演示]

// 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);
}

UPDATE: fixed Chrome desktop and modern mobile browsers with passive listeners

更新:修复了带有被动侦听器的 Chrome 桌面和现代移动浏览器

回答by hallodom

Do it simply by adding a class to the body:

只需在正文中添加一个类即可:

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

Add the class then remove when you want to re-enable scrolling, tested in IE, FF, Safari and Chrome.

添加该类,然后在您想要重新启用滚动时删除,在 IE、FF、Safari 和 Chrome 中进行了测试。

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


For mobile devices, you'll need to handle the touchmoveevent:

对于移动设备,您需要处理touchmove事件:

$('body').bind('touchmove', function(e){e.preventDefault()})

And unbind to re-enable scrolling. Tested in iOS6 and Android 2.3.3

并取消绑定以重新启用滚动。在 iOS6 和 Android 2.3.3 中测试

$('body').unbind('touchmove')

回答by sdleihssirhc

Here's a really basic way to do it:

这是一个非常基本的方法:

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

It's kind of jumpy in IE6.

它在 IE6 中有点跳跃。

回答by Mohammad Anini

The following solution is basic but pure JavaScript (no jQuery):

以下解决方案是基本但纯 JavaScript(无 jQuery):

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

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

回答by Josh Harrison

This solution will maintain the current scroll position whilst scrolling is disabled, unlike some which jump the user back to the top.

此解决方案将在禁用滚动时保持当前滚动位置,这与将用户跳回顶部的某些解决方案不同。

It's based on galambalazs' answer, but with support for touch devices, and refactored as a single object with jquery plugin wrapper.

它基于galambalazs 的答案,但支持触摸设备,并使用 jquery 插件包装器重构为单个对象。

Demo here.

演示在这里。

On github here.

在 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);

回答by lisovaccaro

I'm sorry to answer an old post but I was looking for a solution and came across this question.

我很抱歉回答一个旧帖子,但我正在寻找解决方案并遇到了这个问题。

There are many workarounds for this issue to still display the scrollbar, like giving the container a 100% height and an overflow-y: scrollstyling.

有许多解决方法可以解决此问题以仍然显示滚动条,例如为容器提供 100% 的高度和overflow-y: scroll样式。

In my case I just created a div with a scrollbar which I display while adding overflow: hiddento the body:

就我而言,我刚刚创建了一个带有滚动条的 div,在添加overflow: hidden到正文时显示该滚动条:

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

The element scrollbar must have this styles:

元素滚动条必须具有以下样式:

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

This shows a grey scrollbar, hope it helps future visitors.

这显示了一个灰色滚动条,希望它可以帮助未来的访问者。

回答by Rajat Gupta

I was looking out for a solution to this problem but was not satisfied with the any of the above solutions (as of writing this answer), so I came up with this solution..

我一直在寻找解决此问题的方法,但对上述任何解决方案都不满意(截至撰写此答案时),因此我想出了此解决方案。

CSS

CSS

.scrollDisabled {   
    position: fixed;
    margin-top: 0;// override by JS to use acc to curr $(window).scrollTop()
    width: 100%;
}

JS

JS

var y_offsetWhenScrollDisabled=0;

function disableScrollOnBody(){
    y_offsetWhenScrollDisabled= $(window).scrollTop();
    $('body').addClass('scrollDisabled').css('margin-top', -y_offsetWhenScrollDisabled);
}
function enableScrollOnBody(){
    $('body').removeClass('scrollDisabled').css('margin-top', 0);
    $(window).scrollTop(y_offsetWhenScrollDisabled);
}

回答by jvalen

According to the galambalazspost I would add support for touch devices, allowing us to touch but no scroll up or down:

根据galambalazs帖子,我将添加对触摸设备的支持,允许我们触摸但不能向上或向下滚动:

function disable_scroll() {
   ...
   document.ontouchmove = function(e){ 
        e.preventDefault(); 
   }
}

function enable_scroll() {
   ...
   document.ontouchmove = function(e){ 
     return true; 
   }
}

回答by Hokascha

As of Chrome 56 and other modern browsers, you have to add passive:falseto the addEventListenercall to make preventDefaultwork. So I use this to stop scrolling on mobile:

对于 Chrome 56 和其他现代浏览器,您必须添加passive:falseaddEventListener调用中才能preventDefault工作。所以我用它来停止在移动设备上滚动:

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

function disableScroll(){
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll(){
    document.body.removeEventListener('touchmove', preventDefault, { passive: false });
}

回答by centurian

No, I wouldn't go with event handling because:

不,我不会使用事件处理,因为:

  • not all events are guaranteed to reach body,

  • selecting text and moving downwards actually scrolls the document,

  • if at the phase of event detaching sth goes wrong you are doomed.

  • 并非所有事件都能保证到达身体,

  • 选择文本并向下移动实际上会滚动文档,

  • 如果在事件分离阶段出现问题,你注定要失败。

I've bitten by this by making a copy-paste action with a hidden textarea and guess what, the page scroll whenever I make copy because internally I have to select the textarea before I call document.execCommand('copy').

我通过使用隐藏的 textarea 进行复制粘贴操作而对此感到困惑,猜猜是什么,每当我进行复制时页面都会滚动,因为在内部我必须在调用之前选择 textarea document.execCommand('copy')

Anyway that's the way I go, notice the setTimeout():

无论如何,这就是我要走的路,请注意setTimeout()

document.body.setAttribute('style','overflow:hidden;');
// do your thing...
setTimeout(function(){document.body.setAttribute('style','overflow:visible;');}, 500);

A momentum flashing exists as the scrollbars disappear momentarily but it's acceptable I thing.

当滚动条暂时消失时,存在闪烁的动量,但这是可以接受的。