Як відключити прокрутку тимчасово?


434

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

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


12
Якщо це все ще відображається, то користувач навчений думати, що він повинен функціонувати. Якщо доза не зміниться або доза не реагує, це порушить ментальну модель користувачів щодо того, як ви працюєте на сторінці, і призведе до плутанини. Я просто знайшов би кращий спосіб поводження з прокруткою під час анімації, як, наприклад, зупинка анімації.
Marcus Whybrow

Відповіді:


730

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 і сучасні мобільні браузери з пасивними слухачами


114
Порада для інших розробників, що застрягли в цій пастці: переконайтесь, що ви видаляєте будь-які виклики "e.stopPropagation ()" з інших спроб jQuery припинити прокручування, оскільки це не тільки не працює, але запобігає події переповнення цього коду що працює. Сподіваюся, мої витрачені 30 хвилин допоможуть заощадити інший час :)
Дірк ван Берген

4
Ви можете додати 32 (пробіл) до масиву відключених ключів (показати в коментарях до коду).
gblazex

14
Я можу прокручувати це так, як завжди: за допомогою натискання середньої кнопки та переміщення миші ... Тому цей трюк не вплине на таких користувачів, як я;)
Denis V

11
Панель прокрутки не вимкнена.
verism

8
Це більше не працює на Chrome
PerrierCitror

427

Зробити це просто, додавши клас до тіла:

.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')

4
Зрозумів! Ви повинні поводитися з touchmoveподією, як і з подіями $('body').bind('touchmove', function(e){e.preventDefault()}). Редагував цю відповідь, щоб включити це мобільне рішення.
MusikAnimal

3
Класно, просто потрібно переконатися, що будь-яка внутрішня прокрутка може працювати в режимі монтажу сенсорного пристрою. Можна було зробити накладку безпосередньо під модальним і запобігти натисканню за замовчуванням на накладку замість тіла.
святкування

63
Хоча це рішення працює, воно має (потенційно) небажаний ефект прокрутки вгору сторінки.
Метт

3
Для мене це не спрацювало, якщо мій вибір не був$('body,html')
PickYourPoison

22
Це рішення працює, але смуга прокрутки зникає і створює ефект 'удару' (під вікном os), коли ви застосовуєте цей клас до тіла (наприклад)
Георгіо

57

Ось дійсно основний спосіб зробити це:

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

Це свого роду стрибки в IE6.


14
Насправді не вимкнення, більше схоже на оснащення за замовчуванням при спробі прокрутки.
Marcus Whybrow

11
@Marcus Настільки ж добре, що це станеться з подією, яку не можна скасувати.
sdleihssirhc

3
Незважаючи на те, що він не відключає його по-справжньому, він моделює його, і це досить добре для мене.
Кріс Бір

11
ІМХО - найкраща відповідь тут. Крім того, вам не потрібно блокувати це (0, 0), просто використовуйте поточну позицію прокрутки.
YemSalat

4
Але як ми можемо це відремонтувати?
Кібернетичний

41

Наступне рішення є основним, але чистим JavaScript (без jQuery):

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

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

3
Jumpy в Safari 7.1 та IE 11. Найновіший Chrome, Firefox, Opera ok.
Тімо Кахьонен

Досі крихітний стрибок на новітньому Chrome
Jason Allshorn

Працює прекрасно, в сафарі,
хромірується

Якщо це рішення не працює для певного браузера, тоді проблема з браузерами
Ото Шавадзе,

Як було сказано в іншій відповіді, scroll-behavior: smoothце пояснює. Також я не погоджуюся з тим, що Ото сказав, що це вина браузера. Ви в основному припускаєте, що щось відбудеться миттєво, коли насправді це асинхронно
Метт Флетчер

25

Це рішення дозволить підтримувати поточну позицію прокрутки, поки прокрутка відключена, на відміну від деяких, які стрибають користувача на вершину.

Він заснований на відповіді галамбалазів , але з підтримкою сенсорних пристроїв і відтворений як єдиний об'єкт з обгорткою плагінів 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);

Радий, що це корисно. NB Я редагував посилання на це у форматі плагінів jQuery .
Джош Харрісон

Може допомогти, якщо кнопка прокрутки відключити насправді спрацювала
cameronjonesweb

@ user1672694, він працює тут у Chrome. Який ваш браузер і на якій демо-сторінці ви знайшли помилку? Будь-які помилки JS в консолі?
Джош Харрісон

У Chrome (38, Windows 7) я все ще можу прокручувати, натискаючи та утримуючи середню кнопку вниз, а потім перетягуючи.
Сетхі

1
Будь ласка, ігноруйте, я вважав, що це обов'язково mousewheel спрацювала принадністю
adamj

17

Вибачте, що відповідаю на старий пост, але я шукав рішення і натрапив на це питання.

Існує багато способів вирішення цього питання, щоб все-таки відображати смугу прокрутки, наприклад, надаючи контейнеру 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

Я шукав рішення цієї проблеми, але не був задоволений жодним із вищезазначених рішень ( станом на написання цієї відповіді ), тому придумав це рішення ..

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

Я знайшов , що це працює для мене , якби я додав overflow-y: scrollдо .scrollDisabledстилю. Інакше був невеликий стрибок, оскільки смуга прокрутки щоразу ховалася. Звичайно, це працює тільки для мене, оскільки моя сторінка досить довга, щоб потрібна смуга прокрутки навіть на найбільших екранах.
Ендрю Майнер

7

Відповідно до публікації galambalazs, я б додав підтримку сенсорних пристроїв, що дозволяє нам торкатися, але не прокручувати вгору чи вниз:

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

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

3
Ви впевнені, що це відповідь, а не просто коментар іншої відповіді?
IvanH

6

Що стосується 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 });
}

5

Ні, я б не пішов на обробку подій, оскільки:

  • не всі події гарантовано охоплюють тіло,

  • вибір тексту та переміщення вниз насправді прокручує документ,

  • якщо на фазі від'єднання події що-небудь піде не так, ви приречені.

Я покусав це, зробивши дію копіювання-вставки зі прихованою текстовою ділянкою та здогадайтесь, що, прокручуйте сторінку щоразу, коли я роблю копію, оскільки внутрішньо мені потрібно вибрати текстову область перед тим, як зателефонувати document.execCommand('copy') .

У будь-якому випадку, це те, як я йду, помічайте setTimeout():

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

Імпульс миготіння існує, коли полоси прокрутки миттєво зникають, але це річ прийнятна.


4

Залежно від того, чого ви хочете досягти за допомогою вилученого прокрутки, ви можете просто виправити елемент, з якого потрібно видалити прокрутку (при натисканні або будь-якому іншому тригері, який ви хочете тимчасово відключити прокрутку)

Я шукав рішення "temp no scroll", і для моїх потреб це вирішило

скласти клас

.fixed{
    position: fixed;
}

потім з Jquery

var someTrigger = $('#trigger'); //a trigger button
var contentContainer = $('#content'); //element I want to temporarily remove scroll from

contentContainer.addClass('notfixed'); //make sure that the element has the "notfixed" class

//Something to trigger the fixed positioning. In this case we chose a button.
someTrigger.on('click', function(){

    if(contentContainer.hasClass('notfixed')){
        contentContainer.removeClass('notfixed').addClass('fixed');

    }else if(contentContainer.hasClass('fixed')){
        contentContainer.removeClass('fixed').addClass('notfixed');
    };
});

Я виявив, що це досить просте рішення, яке добре працює на всіх браузерах, а також забезпечує просте використання на портативних пристроях (тобто iPhone, планшетах тощо). Оскільки елемент тимчасово зафіксований, прокрутки немає :)

ПРИМІТКА! Залежно від розміщення елемента "contentContainer", можливо, знадобиться його відрегулювати зліва. Що легко зробити, додавши ліве значення css до цього елемента, коли фіксований клас активний

contentContainer.css({
    'left': $(window).width() - contentContainer.width()/2 //This would result in a value that is the windows entire width minus the element we want to "center" divided by two (since it's only pushed from one side)
});

4

Ще одне рішення:

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

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

Це дві функції, які я використовую для показу свого спливаючого / модального режиму:

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.


Це працювало для мене, і проблема прокрутки до верху після використання позиції: виправлена. Дякую тобі!
Аннія Мартінес

3

Як щодо цього? (Якщо ви використовуєте jQuery)

var $window = $(window);
var $body = $(window.document.body);

window.onscroll = function() {
    var overlay = $body.children(".ui-widget-overlay").first();

    // Check if the overlay is visible and restore the previous scroll state
    if (overlay.is(":visible")) {
        var scrollPos = $body.data("scroll-pos") || { x: 0, y: 0 };
        window.scrollTo(scrollPos.x, scrollPos.y);
    }
    else {
        // Just store the scroll state
        $body.data("scroll-pos", { x: $window.scrollLeft(), y: $window.scrollTop() });
    }
};

трохи стрибає, але це працює для IE 7 (клієнт використовує це). інших рішень немає.
niki b

3

Я використовую showModalDialog для показу вторинної сторінки як модального діалогового вікна.

щоб приховати смуги прокрутки головного вікна:

document.body.style.overflow = "hidden";

і при закритті діалогового діалогового вікна показують смуги прокрутки головного вікна:

document.body.style.overflow = "scroll";

для доступу до елементів у головному вікні з діалогового вікна:

parent.document.getElementById('dialog-close').click();

лише для тих, хто шукає про showModalDialog : (після рядка 29 оригінального коду)

document.getElementById('dialog-body').contentWindow.dialogArguments = arg;
document.body.style.overflow = "hidden";//****
document.getElementById('dialog-close').addEventListener('click', function(e) {
    e.preventDefault();
    document.body.style.overflow = "scroll";//****
    dialog.close();
});

Це працювало для мене в React, де jQuery не існує і де React не має доступу для управління станом тегу body.
Jon

3

Скасування події, як у прийнятій відповіді, є жахливим методом, на мою думку: /

Натомість я використовував position: fixed; top: -scrollTop();нижче.

Демонстрація: https://jsfiddle.net/w9w9hthy/5/

З мого спливаючого проекту jQuery: https://github.com/seahorsepip/jPopup

//Freeze page content scrolling
function freeze() {
    if($("html").css("position") != "fixed") {
        var top = $("html").scrollTop() ? $("html").scrollTop() : $("body").scrollTop();
        if(window.innerWidth > $("html").width()) {
            $("html").css("overflow-y", "scroll");
        }
        $("html").css({"width": "100%", "height": "100%", "position": "fixed", "top": -top});
    }
}

//Unfreeze page content scrolling
function unfreeze() {
    if($("html").css("position") == "fixed") {
        $("html").css("position", "static");
        $("html, body").scrollTop(-parseInt($("html").css("top")));
        $("html").css({"position": "", "width": "", "height": "", "top": "", "overflow-y": ""});
    }
}

Цей код враховує проблеми ширини, висоти, смуги прокрутки та перемикання сторінок.

Можливі проблеми, вирішені вищевказаним кодом:

  • ширина, при встановленому положенні фіксований розмір елемента html може бути менше 100%
  • висота, така ж, як і вище
  • смугу прокрутки, коли налаштовано положення змісту, вміст сторінки більше не має смуги прокрутки, навіть якщо на ній була смуга прокрутки, перш ніж виходила з горизонтального перемикання сторінки
  • pagejump, при встановленому положенні виправлено сторінку scrollTop більше не діє, що призводить до вертикального переходу сторінки

Якщо хтось вдосконалив код заморожування / відмороження вищезгаданої сторінки, повідомте мене, щоб я міг додати ці покращення до свого проекту.


3
var winX = null, 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;
};

1
Тут найкраще рішення.
jfunk

@jfunk згоден, простий і стислий, невеликий код, ідеальний. Дякую
Флорент Рокес

2

У мене така ж проблема, нижче - спосіб, з яким я її вирішую.

/* file.js */
var body = document.getElementsByTagName('body')[0];
//if window dont scroll
body.classList.add("no-scroll");
//if window scroll
body.classList.remove("no-scroll");

/* file.css */
.no-scroll{
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

сподіваюся, що ця допомога.


1

Спираючись на відповідь Cheyenne Forbes, і одну, яку я знайшов тут за допомогою fcalderan: Просто вимкніть прокрутку, не приховайте її? і виправити питання про те, що зникає смуга прокрутки від Hallodom

CSS:

.preventscroll{
    position: fixed;
    overflow-y:scroll;
}

JS:

whatever.onclick = function(){
    $('body').addClass('preventscroll');
}
whatevertoclose.onclick = function(){
    $('body').removeClass('preventscroll');
}

Цей код вас стрибає вгору сторінки, але я думаю, що код fcalderan має вирішення.


1

Я знаю, що це давнє запитання, але мені довелося зробити щось дуже схоже, і через деякий час шукаючи відповіді та пробуючи різні підходи, я в кінцевому підсумку використовував дуже просте рішення.

Моя проблема була дуже схожа, майже однакова, єдина різниця в тому, що мені не довелося фактично показувати смугу прокрутки - я просто повинен був переконатися, що її ширина все-таки буде використовуватися, щоб ширина сторінки не змінювалася під час відображення мого накладання .

Коли я починаю ковзати накладку на екран, я роблю:

$('body').addClass('stop-scrolling').css('margin-right', 8);

і після того, як я зсуну накладку з екрану, я виконую:

$('body').removeClass('stop-scrolling').css('margin-right', 0);

ВАЖЛИВО: Це прекрасно працює, оскільки моя накладка розташована absolute, right: 0pxколи visible.


1

Найпростіший метод:

$("body").css("overflow", "hidden"); // Remove the scroll bar temporarily

Щоб скасувати його:

$("body").css("overflow", "auto");

Легко здійснити, але єдиний недолік - це:

  • Сторінка трохи підскочить вліво, якщо вона розташована по центру (по горизонталі).

Це пов’язано з тим, що видаляється смуга прокрутки, а вікно перегляду стає трохи ширшим.


1
це скине положення прокрутки
Ангел Девід Кальдераро Паччіотт

@AngelDavidCalderaroPacciott Ні, позиція прокрутки залишиться такою ж висотою / відстані.
Даан

@Daan це скидає положення прокрутки в Chrome
Том

@Тому я щойно перевірив це, він робить це лише в деяких випадках (коли зріст тіла не стосується дітей). Спробуйте змінити bodyна html.
Даан

Б'юсь об заклад, ви не перевірили своє рішення в Iphone, бо overflow:hiddenтам не працює
Шуво

1

Ось моє рішення зупинити прокрутку (немає jQuery). Я використовую його для відключення прокрутки, коли з’являється бічне меню.

<button onClick="noscroll()" style="position:fixed; padding: 8px 16px;">Disable/Enable scroll</button>
<script>
var noscroll_var;
function noscroll(){
  if(noscroll_var){
    document.getElementsByTagName("html")[0].style.overflowY = "";
    document.body.style.paddingRight = "0";
    noscroll_var = false
  }else{
    document.getElementsByTagName("html")[0].setAttribute('style', 'overflow-y: hidden !important');
    document.body.style.paddingRight = "17px";
    noscroll_var = true
  }
}/*noscroll()*/
</script>

<!-- Just to fill the page -->
<script>
  for(var i=0; i <= 80; i++){
    document.write(i + "<hr>")
  }
</script>

Я поклав 17px padding-right, щоб компенсувати зникнення смуги прокрутки. Але це також проблематично, переважно для мобільних браузерів. Вирішується шляхом отримання ширини бруска відповідно до цього .

Всі разом у цій ручці.



1

Це найпростіше рішення, яке я отримав поки що. І повірте, я спробував усі інші, і це найпростіший. Він чудово працює на пристроях Windows , що відсуває сторінку праворуч, щоб мати місце для системної панелі прокрутки та пристроїв IOS, які не потребують місця для своїх смуг прокрутки в браузерах. Отже, використовуючи це, вам не потрібно буде додавати набивання праворуч, щоб сторінка не мерехтіла, коли ви ховаєте переповнення тіла або html з допомогою css .

Рішення досить просте, якщо задуматися. Ідея полягає у наданні window.scrollTop () такої ж точної позиції в момент відкриття спливаючого вікна. Також змініть це положення, коли вікно змінить розмір (як положення прокрутки змінюється, як тільки це відбувається).

Тож ось ми йдемо ...

Спочатку даємо змогу створити змінну, яка дозволить вам знати, що спливаюче вікно відкрите, і назвіть його stopWindowScroll . Якщо ми цього не зробимо, ви отримаєте помилку невизначеної змінної на своїй сторінці та встановите її на 0 - як неактивну.

$(document).ready(function(){
    stopWindowScroll = 0;
});

Тепер давайте зробимо функцію відкритого спливаючого меню відьмою будь-яку функцію у вашому коді, яка запускає будь-яке спливаюче вікно, яке ви використовуєте як плагін або звичай. У цьому випадку це буде звичайне спеціальне спливаюче вікно з простим документом про функцію клацання.

$(document).on('click','.open-popup', function(){
    // Saving the scroll position once opening the popup.
    stopWindowScrollPosition = $(window).scrollTop();
    // Setting the stopWindowScroll to 1 to know the popup is open.
    stopWindowScroll = 1;
    // Displaying your popup.
    $('.your-popup').fadeIn(300);
});

Отже, наступне, що ми робимо - це створити функцію закриття спливаючих вікон, яку я повторюю знову, це будь-яка функція, яку ви вже створили або використовуєте в плагіні. Важливо те, що нам потрібні ці 2 функції, щоб встановити змінну stopWindowScroll на 1 або 0, щоб знати, коли вона відкрита чи закрита.

$(document).on('click','.open-popup', function(){
    // Setting the stopWindowScroll to 0 to know the popup is closed.
    stopWindowScroll = 0;
    // Hiding your popup
    $('.your-popup').fadeOut(300);
});

Тоді давайте створимо функцію window.scroll, щоб ми могли запобігти прокрутці, як тільки згаданий вище stopWindowScroll встановлений на 1 - як активний.

$(window).scroll(function(){
    if(stopWindowScroll == 1) {
         // Giving the window scrollTop() function the position on which
         // the popup was opened, this way it will stay in its place.
         $(window).scrollTop(stopWindowScrollPosition);
    }
});

Це воно. Для цього не потрібен CSS, окрім власних стилів для сторінки. Це спрацювало як шарм для мене, і я сподіваюся, що це допоможе вам та іншим.

Ось робочий приклад JSFiddle:

JS Fiddle Приклад

Повідомте мене, чи допомогло це. З повагою


1

Збережіть довжину прокрутки у глобальній змінній та відновіть її за потреби!

var sctollTop_length = 0;

function scroll_pause(){
  sctollTop_length = $(window).scrollTop();
  $("body").css("overflow", "hidden");
}

function scroll_resume(){
  $("body").css("overflow", "auto");
  $(window).scrollTop(sctollTop_length);
}

1

Цей код працюватиме в Chrome 56 і далі (оригінальна відповідь більше не працює в Chrome).

Використовуйте DomUtils.enableScroll()для включення прокрутки.

Використовуйте DomUtils.disableScroll()для відключення прокрутки.

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

  static preventDefault(e) {
    e = e || window.event;
    if (e.preventDefault) e.preventDefault();
    e.returnValue = false;
  }

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

  static disableScroll() {
    document.addEventListener('wheel', DomUtils.preventDefault, {
      passive: false,
    }); // Disable scrolling in Chrome
    document.addEventListener('keydown', DomUtils.preventDefaultForScrollKeys, {
      passive: false,
    });
  }

  static enableScroll() {
    document.removeEventListener('wheel', DomUtils.preventDefault, {
      passive: false,
    }); // Enable scrolling in Chrome
    document.removeEventListener(
      'keydown',
      DomUtils.preventDefaultForScrollKeys,
      {
        passive: false,
      }
    ); // Enable scrolling in Chrome
  }
}

1

Щоб запобігти стрибку, це те, що я використав

export function toggleBodyScroll(disable) {
  if (!window.tempScrollTop) {
    window.tempScrollTop = window.pageYOffset; 
    // save the current position in a global variable so I can access again later

  }
  if (disable) {
    document.body.classList.add('disable-scroll');
    document.body.style.top = `-${window.tempScrollTop}px`;
  } else {
    document.body.classList.remove('disable-scroll');
    document.body.style.top = `0px`;
    window.scrollTo({top: window.tempScrollTop});
    window.tempScrollTop = 0;
  }
}

і в моєму css

.disable-scroll {
  height: 100%;
  overflow: hidden;
  width: 100%;
  position: fixed;
}

0

Я знайшов цю відповідь на іншому сайті :

Вимкнути прокрутку:

$( ".popup").live({
    popupbeforeposition: function(event, ui) {
    $("body").on("touchmove", false);
}
});

Після закриття спливаючого випуску прокрутіть:

$( ".popup" ).live({
    popupafterclose: function(event, ui) {
    $("body").unbind("touchmove");
}
});

Це, здається, не зупиняє сенсорне прокручування, але прокручування миші, клавіші зі стрілками, клавіші вгору та вниз клавішами тощо все одно працюватимуть. -1
markasoftware

Ці "події" призначені для прокрутки на дотик, просто підміняйте всі необхідні події.
pennstump

1
Крім того, це, здається, використовується в якійсь іншій дуже специфічній ситуації. попппозиція? Для чого це повинно бути? Що це стосується тимчасового відключення прокрутки? Принаймні, зробіть це доречним у цій ситуації. Схоже, ви скопіювали це безпосередньо з веб-сайту.
markasoftware

0

рішення галамбалаза чудово! Це прекрасно працювало для мене і в Chrome, і в Firefox. А також його можна розширити, щоб запобігти будь-якій події за замовчуванням у вікні браузера. Скажімо, ви робите додаток на полотні. Ви можете це зробити:

var events = {
  preventDefault: function(e) {
    e = e || window.event;
    if (e.preventDefault) e.preventDefault();
    e.returnValue = false;  
  },

  //spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36,
  //left: 37, up: 38, right: 39, down: 40
  keys: [32, 33, 34, 35, 36, 37, 38, 39, 40],
  keydown: function(e) {
    for (var i = events.keys.length; i--;) {
      if (e.keyCode === events.keys[i]) {
        events.preventDefault(e);
        return;
      }
    }
  },

  wheel: function(e) {
    events.preventDefault(e);
  },

  disable: function() {
    if (window.addEventListener) {
      window.addEventListener('DOMMouseScroll', events.wheel, false);
    }
    window.onmousewheel = document.onmousewheel = events.wheel;
    document.onkeydown = helpers.events.keydown;
  },

  enable: function() {
    if (window.removeEventListener) {
      window.removeEventListener('DOMMouseScroll', events.wheel, false);
    }
    window.onmousewheel = document.onmousewheel = document.onkeydown = null;  
  }
}

А потім у вашому додатку скажімо, що ви збираєтеся обробляти власні події, наприклад, миша, клавіатура, події на дотику тощо. Ви можете вимкнути події за замовчуванням, коли миша йде всередину полотна, і знову ввімкнути їх, коли миша виходить:

function setMouseEvents(canvas) {
  var useCapture = false;

  //Mouse enter event
  canvas.addEventListener('mouseenter', function(event) {
    events.disable();
  }, useCapture);

  //Mouse leave event
  canvas.addEventListener('mouseleave', function(event) {
    events.enable();
  }, useCapture);
}

Ви навіть можете відключити меню правої кнопки миші за допомогою цього злому:

function disableRightClickMenu(canvas) {
  var my_gradient = canvas.context.createLinearGradient(0, 0, 0, 225);
  my_gradient.addColorStop(0, "white");
  my_gradient.addColorStop(1, "white");
  canvas.context.fillStyle = my_gradient;
  canvas.context.fillRect(0, 0, canvas.width, canvas.height);
  canvas.oncontextmenu = function() { return false; };
}

0

У мене була аналогічна проблема з анімацією на екранах мобільних пристроїв, але не на ноутбуках, коли я намагався анімувати діву за допомогою команди анімації jquery. Тому я вирішив використовувати таймер, який так часто відновлює положення прокрутки вікна, що неозброєним оком документ буде здаватися статичним. Це рішення прекрасно працювало на маленькому мобільному пристрої, як Samsung Galaxy-2 або iphone-5.

Основна логіка такого підходу : Таймер для встановлення положення прокрутки вікна на вихідне положення прокрутки слід запустити перед командою jquery animite, і тоді, коли анімація завершена, нам потрібно очистити цей таймер (original scroll position це положення безпосередньо перед запуском анімації).

Я приємно здивував, що документ насправді виявився статичним під час тривалості анімації, якщо був інтервал таймера 1 millisecond, на що я прагнув.

//get window scroll position prior to animation
//so we can keep this position during animation
var xPosition = window.scrollX || window.pageXOffset || document.body.scrollLeft;
var yPosition = window.scrollY || window.pageYOffset || document.body.scrollTop;

//NOTE:restoreTimer needs to be global variable
//start the restore timer
restoreTimer = setInterval(function() {
    window.scrollTo(xPosition, yPosition);
}, 1);

//animate the element emt
emt.animate({
    left: "toggle",
    top: "toggle",
    width: "toggle",
    height: "toggle"
}, 500, function() {
    //when animation completes, we stop the timer
    clearInterval(restoreTimer);
});

ДРУГІ РІШЕННЯ, які спрацювали : На основі відповіді Мохаммада Аніні під цим повідомленням, щоб увімкнути / вимкнути прокрутку, я також виявив, що модифікована версія коду, як показано нижче, працює.

//get current scroll position
var xPosition = window.scrollX || window.pageXOffset || document.body.scrollLeft;
var yPosition = window.scrollY || window.pageYOffset || document.body.scrollTop;

//disable scrolling
window.onscroll = function() {
    window.scrollTo(xPosition, yPosition);
};

//animate and enable scrolling when animation is completed
emt.animate({
    left: "toggle",
    top: "toggle",
    width: "toggle",
    height: "toggle"
}, 500, function() {
    //enable scrolling when animation is done
    window.onscroll = function() {};
});

0

Просте рішення, яке працювало для мене (відключення прокрутки вікна тимчасово).

На основі цієї загадки: http://jsfiddle.net/dh834zgw/1/

наступний фрагмент (за допомогою jquery) відключить прокрутку вікна:

 var curScrollTop = $(window).scrollTop();
 $('html').toggleClass('noscroll').css('top', '-' + curScrollTop + 'px');

І у вашому css:

html.noscroll{
    position: fixed;
    width: 100%;
    top:0;
    left: 0;
    height: 100%;
    overflow-y: scroll !important;
    z-index: 10;
 }

Тепер, коли ви видалите модальний модуль, не забудьте видалити клас noscroll з html-тегу:

$('html').toggleClass('noscroll');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.