Как временно отключить прокрутку? - PullRequest
396 голосов
/ 22 января 2011

Я использую плагин scrollTo jQuery и хотел бы знать, возможно ли как-то временно отключить прокрутку элемента окна через Javascript?Причина, по которой я хотел бы отключить прокрутку, состоит в том, что когда вы прокручиваете, когда scrollTo анимирует, это становится действительно уродливым;)

Конечно, я мог бы сделать $("body").css("overflow", "hidden"); и затем вернуть его в автоматический режим, когдаанимация останавливается, но было бы лучше, если бы полоса прокрутки была видна, но не активна.

Ответы [ 33 ]

676 голосов
/ 22 января 2011

Событие 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 = e || window.event;
  if (e.preventDefault)
      e.preventDefault();
  e.returnValue = false;  
}

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

function disableScroll() {
  if (window.addEventListener) // older FF
      window.addEventListener('DOMMouseScroll', preventDefault, false);
  document.addEventListener('wheel', preventDefault, {passive: false}); // Disable scrolling in Chrome
  window.onwheel = preventDefault; // modern standard
  window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE
  window.ontouchmove  = preventDefault; // mobile
  document.onkeydown  = preventDefaultForScrollKeys;
}

function enableScroll() {
    if (window.removeEventListener)
        window.removeEventListener('DOMMouseScroll', preventDefault, false);
    document.removeEventListener('wheel', preventDefault, {passive: false}); // Enable scrolling in Chrome
    window.onmousewheel = document.onmousewheel = null; 
    window.onwheel = null; 
    window.ontouchmove = null;  
    document.onkeydown = null;  
}

РЕДАКТИРОВАНИЕ

Добавлено document.addEventListener('wheel', preventDefault, {passive: false});, чтобы гарантировать, что функция все еще работает в Chrome.

404 голосов
/ 23 августа 2012

Сделайте это просто, добавив класс к телу:

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

Добавьте класс и удалите его, если хотите снова включить прокрутку, протестировано в IE, FF, Safari и Chrome.

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

Для мобильных устройств вам необходимо обработать событие touchmove:

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

и отменить привязку, чтобы снова включить прокрутку,Протестировано в iOS6 и Android 2.3.3

$('body').unbind('touchmove')
51 голосов
/ 22 января 2011

Вот действительно простой способ сделать это:

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

Это немного нервно в IE6.

31 голосов
/ 04 октября 2014

Следующее решение является базовым, но чистым JavaScript (без jQuery):

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

function enableScrolling(){
    window.onscroll=function(){};
}
25 голосов
/ 03 февраля 2014

Это решение будет поддерживать текущую позицию прокрутки, пока прокрутка отключена, в отличие от некоторых, которые возвращают пользователя наверх.

Он основан на ответе 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);
14 голосов
/ 29 февраля 2012

Извините, что отвечаю на старый пост, но я искал решение и наткнулся на этот вопрос.

Есть много способов обойти эту проблему, чтобы по-прежнему отображать полосу прокрутки, например, присвоить контейнеру 100% высоты и стиль overflow-y: scroll.

В моем случае я только что создал div с полосой прокрутки, которую я отображаю при добавлении 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;

Это показывает серую полосу прокрутки, надеюсь, это поможет будущим посетителям.

8 голосов
/ 09 ноября 2014

Я искал решение этой проблемы, но не был удовлетворен каким-либо из вышеперечисленных решений ( на момент написания этого ответа ), поэтому я нашел это решение ..

CSS

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

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);
}
7 голосов
/ 23 августа 2013

Согласно сообщению galambalazs , я бы добавил поддержку сенсорных устройств, позволяя нам касаться, но не прокручивать вверх или вниз:

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

function enable_scroll() {
   ...
   document.ontouchmove = function(e){ 
     return true; 
   }
}
4 голосов
/ 26 сентября 2017

Начиная с Chrome 56 и других современных браузеров, вы должны добавить passive:false к вызову addEventListener, чтобы preventDefault заработал. Поэтому я использую это, чтобы остановить прокрутку на мобильном телефоне:

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

function disableScroll(){
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll(){
    document.body.removeEventListener('touchmove', preventDefault, { passive: false });
}
4 голосов
/ 26 сентября 2013

Другое решение:

body {
    overflow-y: scroll;
    width: 100%;
    margin: 0 auto;
}

Таким образом, у вас всегда есть вертикальная полоса прокрутки, но, поскольку большая часть моего контента длиннее, чем область просмотра, это нормально для меня.Контент центрируется с помощью отдельного элемента div, но без установки поля в тексте, мой контент останется слева.

Это две функции, которые я использую для отображения моего всплывающего окна / модальное:

var popup_bodyTop = 0;
var popup_bodyLeft = 0;

function popupShow(id)
{
    $('#'+ id).effect('fade');
    $('#popup-overlay').effect('fade');

    // remember current scroll-position
    // because when setting/unsetting position: fixed to body
    // the body would scroll to 0,0
    popup_bodyLeft = $(document).scrollLeft();
    popup_bodyTop  = $(document).scrollTop();

    // invert position
    var x = - popup_bodyLeft;
    var y = - popup_bodyTop;

    $('body').css('position', 'fixed');
    $('body').css('top', y.toString() +'px');
    $('body').css('left', x.toString() +'px');
}

function popupHide(id)
{
    $('#'+ id).effect('fade');
    $('#popup-overlay').effect('fade');
    $('body').css('position', '');
    $('html, body').scrollTop(popup_bodyTop);
    $('html, body').scrollLeft(popup_bodyLeft);
}

Результат: не прокручиваемый фон и перестановка содержимого из-за левой полосы прокрутки.Протестировано с текущими FF, Chrome и IE 10.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...