Como desativar a rolagem temporariamente?


434

Estou usando o plugin scrollTo jQuery e gostaria de saber se é possível desabilitar temporariamente a rolagem no elemento da janela por meio de Javascript? O motivo pelo qual eu gostaria de desativar a rolagem é que, quando você rola enquanto scrollTo está animando, fica realmente feio;)

Obviamente, eu poderia fazer um $("body").css("overflow", "hidden");e colocá-lo novamente no modo automático quando a animação parar, mas seria melhor se a barra de rolagem ainda estivesse visível, mas inativa.


12
Se ainda estiver sendo exibido, o usuário será treinado para pensar que deve estar funcionando. Se a dose não se mover ou a dose não responder, isso quebrará o modelo mental do usuário de como a página funciona e resultará em confusão. Eu apenas encontraria uma maneira melhor de lidar com a rolagem durante a animação, como, por exemplo, interromper a animação.
Marcus Whybrow

Respostas:


731

O scrollevento não pode ser cancelado. Mas você pode fazer isso cancelando estes eventos de interação: Rolagem do
mouse e toque e Botões associados à rolagem.

[ Demo de trabalho ]

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

ATUALIZAÇÃO: área de trabalho fixa do Chrome e navegadores móveis modernos com ouvintes passivos


114
Dica para outros desenvolvedores presos nessa armadilha: remova toda e qualquer chamada 'e.stopPropagation ()' de outras tentativas do jQuery para interromper a rolagem, porque isso não apenas não funciona, mas também impede que o evento borbulhe para ESTE código isso funciona. Espero que meus desperdiçados 30 minutos vai ajudar a salvar alguém vez mais :)
Dirk van Bergen

4
Você pode adicionar 32 (espaço) à matriz de chaves desabilitadas (mostrada nos comentários do código).
gblazex

14
I pode rolar esta como sempre faço: usando imprensa botão do meio e movendo o mouse ... Portanto, este truque não vai afetar esses usuários como me;)
Denis V

11
A barra de rolagem não está desativada.
Verism

8
Isso não funciona mais no Chrome
PerrierCitror

427

Faça isso simplesmente adicionando uma classe ao corpo:

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

Adicione a classe e remova quando desejar reativar a rolagem, testada no IE, FF, Safari e Chrome.

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

Para dispositivos móveis , você precisará lidar com o touchmoveevento:

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

E desative para reativar a rolagem. Testado no iOS6 e Android 2.3.3

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

4
Entendi! Você tem que lidar com o touchmoveevento, como acontece com $('body').bind('touchmove', function(e){e.preventDefault()}). Editou esta resposta para incluir esta solução móvel.
MusikAnimal

3
Legal, basta garantir que qualquer rolagem interna funcione no modal do dispositivo de toque. Poderia fazer uma sobreposição logo abaixo do modal e impedir o movimento de toque padrão na sobreposição, em vez de no corpo.
hallodom

63
Embora essa solução funcione, ela tem o efeito (potencialmente) indesejável de rolar de volta para o topo da página.
Matt

3
Isso não funcionou para mim, a menos que meu seletor fosse$('body,html')
PickYourPoison

22
Esta solução funciona, mas a barra de rolagem desaparecer e criar um efeito de 'bater' (sob a janela os) quando aplicar esta classe para o corpo (por exemplo)
Georgio

57

Aqui está uma maneira realmente básica de fazer isso:

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

É meio nervoso no IE6.


14
Não é realmente uma desativação, mais como um snap ao padrão quando a rolagem é tentada.
Marcus Whybrow

11
@ Marcus Tão bom quanto será com um evento que não é cancelável.
sdleihssirhc

3
Mesmo que não o desative de verdade, ele simula e isso é bom o suficiente para mim.
Chris Bier

11
IMHO - melhor resposta aqui. Além disso, você não precisa travar (0, 0), basta usar a posição atual de rolagem.
YemSalat 20/05

4
Mas como a reativamos?
23719 Cybernetic

41

A solução a seguir é JavaScript básico, mas puro (sem 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 no Safari 7.1 e IE 11. Mais novo, Chrome, Firefox, Opera ok.
Timo Kähkönen

Ainda um pouco nervoso no mais novo Chrome
Jason Allshorn 13/18

Funcionando bem, no Safari, Chrome, mas brilhou nos IE
Bhuvan Arora

Se esta solução não funciona para alguns navegador, então isso é problema navegadores
Oto Shavadze

Como mencionado em outra resposta, scroll-behavior: smoothbucks isso. Além disso, eu discordo de Oto dizendo que a culpa é do navegador. Você está basicamente assumindo que algo acontecerá instantaneamente quando, na realidade, é assíncrono
Matt Fletcher

25

Esta solução manterá a posição atual de rolagem enquanto a rolagem estiver desativada, ao contrário de algumas que fazem o usuário voltar ao topo.

É baseado na resposta dos galambalazs , mas com suporte para dispositivos de toque e refatorado como um único objeto com o invólucro do plugin jquery.

Demonstração aqui.

No github aqui.

/**
 * $.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);

Ainda bem que é útil. Nota: eu editei com um link para isso no formato do plugin jQuery .
Josh Harrison

Pode ajudar se o botão de rolagem desativar efectivamente trabalhadas
cameronjonesweb

@ user1672694, ele funciona aqui no Chrome. Qual é o seu navegador e em qual página de demonstração você encontrou o bug? Algum erro de JS no console?
Josh Harrison

No Chrome (38, Windows 7), ainda posso rolar clicando e mantendo o botão do meio pressionado e arrastando.
Sethi

1
Por favor, desrespeito, eu achei que a ligação que mousewheeltrabalhou um charme
adamj

17

Lamento responder a uma postagem antiga, mas estava procurando uma solução e me deparei com essa pergunta.

Existem várias soluções alternativas para esse problema ainda exibir a barra de rolagem, como fornecer ao contêiner uma altura de 100% e um overflow-y: scroll estilo.

No meu caso, acabei de criar uma div com uma barra de rolagem que exibo enquanto adicionava overflow: hiddenao corpo:

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

A barra de rolagem do elemento deve ter estes estilos:

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

Isso mostra uma barra de rolagem cinza, espero que ajude futuros visitantes.


8

Eu estava procurando uma solução para esse problema, mas não estava satisfeito com nenhuma das soluções acima ( ao escrever esta resposta ), por isso vim com essa solução ..

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

Eu achei que isso funcionou para mim se eu adicionasse overflow-y: scrollao .scrollDisabledestilo. Caso contrário, houve um pequeno salto à medida que a barra de rolagem se ocultava a cada vez. Claro, isso só funciona para mim porque minha página é longa o suficiente para precisar de uma barra de rolagem, mesmo nas telas maiores.
Andrew Miner

7

De acordo com o post dos galambalazs, eu adicionaria suporte para dispositivos de toque, permitindo tocar, mas sem rolar para cima ou para baixo:

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

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

3
Tem certeza de que é uma resposta e não apenas um comentário de outra resposta?
precisa saber é o seguinte

6

No Chrome 56 e em outros navegadores modernos, você precisa adicionar passive:falseà addEventListenerchamada para fazer o preventDefaulttrabalho. Então, eu uso isso para parar de rolar no celular:

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

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

5

Não, eu não aceitaria a manipulação de eventos porque:

  • nem todos os eventos têm garantia de atingir o corpo,

  • selecionar texto e mover para baixo, na verdade, rola o documento,

  • se na fase do evento desanexar sth der errado, você estará condenado.

Mordi isso ao fazer uma ação de copiar e colar com uma área de texto oculta e, adivinhe, a página rola sempre que eu faço uma cópia, porque internamente eu tenho que selecionar a área de texto antes de ligar document.execCommand('copy') .

Seja como for, observe o setTimeout():

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

Existe um momento piscando quando as barras de rolagem desaparecem momentaneamente, mas é aceitável.


4

Dependendo do que você deseja alcançar com a rolagem removida, basta corrigir o elemento do qual deseja remover a rolagem (ao clicar ou qualquer outro gatilho que você deseja desativar temporariamente a rolagem)

Eu estava procurando por uma solução "temp no scroll" e por minhas necessidades, isso resolveu

faça uma aula

.fixed{
    position: fixed;
}

então com 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');
    };
});

Descobri que essa era uma solução bastante simples que funciona bem em todos os navegadores e também facilita o uso em dispositivos portáteis (como iPhones, tablets etc.). Como o elemento está temporariamente corrigido, não há rolagem :)

NOTA! Dependendo do posicionamento do seu elemento "contentContainer", pode ser necessário ajustá-lo da esquerda. O que pode ser feito facilmente adicionando um valor à esquerda do css nesse elemento quando a classe fixa está ativa

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

Outra solução:

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

Dessa forma, você sempre tem uma barra de rolagem vertical, mas como a maior parte do meu conteúdo é maior que a janela de visualização, isso é bom para mim. O conteúdo é centralizado com uma div separada, mas sem definir a margem novamente no corpo, meu conteúdo permaneceria à esquerda.

Estas são as duas funções que eu uso para mostrar meu popup / modal:

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

Resultado: fundo sem rolagem e sem reposicionamento do conteúdo por causa da barra de rolagem esquerda. Testado com o FF atual, Chrome e IE 10.


Isso funcionou para mim e o problema de rolar para o topo depois de usar position: fixed. Obrigado!
Annia Martinez

3

Que tal agora? (Se você estiver usando 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() });
    }
};

um pouco nervoso, mas isso funciona para o IE 7 (o cliente usa). outras soluções não.
Niki b

3

Estou usando showModalDialog , para mostrar a página secundária como caixa de diálogo modal.

ocultar barras de rolagem da janela principal:

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

e ao fechar a caixa de diálogo modal, mostrando as barras de rolagem da janela principal:

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

para acessar elementos na janela principal a partir da caixa de diálogo:

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

apenas para quem pesquisar sobre showModalDialog : (após a linha 29 do código original)

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

Isso funcionou para mim no React, onde o jQuery não existe e onde o React não tem acesso para gerenciar o estado da tag body.
22416 Jon

3

Cancelar o evento como na resposta aceita é um método horrível na minha opinião: /

Em vez disso, usei position: fixed; top: -scrollTop();abaixo.

Demonstração: https://jsfiddle.net/w9w9hthy/5/

No meu projeto pop-up do 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": ""});
    }
}

Esse código leva em consideração os problemas de largura, altura, barra de rolagem e salto de página.

Possíveis problemas resolvidos com o código acima:

  • largura, ao definir a posição fixa, a largura do elemento html pode ser menor que 100%
  • altura, o mesmo que acima
  • barra de rolagem, ao definir a posição fixa, o conteúdo da página não tem mais uma barra de rolagem, mesmo quando ela tinha uma barra de rolagem antes de resultar em um salto de página horizontal
  • pagejump, ao definir a posição fixa, o scrollTop da página não é mais eficaz, resultando em um salto de página vertical

Se alguém tiver alguma melhoria no código de congelamento / descongelamento da página acima, avise-me para que eu possa adicionar essas melhorias ao meu projeto.


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
Esta é a melhor solução aqui.
jfunk 15/03

@jfunk concorda, simples e conciso, pequeno código, perfeito. Obrigado
Florent Roques

2

Eu tenho o mesmo problema, abaixo está a minha maneira de lidar com isso.

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

Espero que isso ajude.


1

Com base na resposta de Cheyenne Forbes, e uma que encontrei aqui via fcalderan: Apenas desative o scroll, não o oculte? e para corrigir o problema de Hallodom da barra de rolagem desaparecer

CSS:

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

JS:

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

Esse código o leva ao topo da página, mas acho que o código do fcalderan tem uma solução alternativa.


1

Sei que essa é uma pergunta antiga, mas tive que fazer algo muito semelhante e, depois de algum tempo procurando uma resposta e tentando abordagens diferentes, acabei usando uma solução muito fácil.

Meu problema era muito semelhante, quase idêntico, a única diferença é que eu não precisava mostrar a barra de rolagem - só precisava garantir que sua largura ainda fosse usada, para que a largura da página não mudasse enquanto minha sobreposição fosse exibida .

Quando começo a deslizar minha sobreposição na tela, faço:

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

e depois que deslizo minha sobreposição da tela, faço:

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

IMPORTANTE: isso funciona perfeitamente porque minha sobreposição está posicionada absolute, right: 0pxquando visible.


1

O método mais simples é:

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

Para desfazê-lo:

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

Fácil de implementar, mas a única desvantagem é:

  • A página pulará um pouco para a esquerda se estiver alinhada ao centro (horizontalmente).

Isso ocorre porque a barra de rolagem é removida e a janela de exibição se torna um pouco maior.


1
que irá redefinir a posição de rolagem
Angel David Calderaro Pacciott

@AngelDavidCalderaroPacciott Não, a posição de rolagem permanecerá na mesma altura / distância.
Daan

@Daan ele faz redefinir a posição de rolagem no Chrome
Tom

@ Tom Acabei de verificar, ele só o faz em algumas ocasiões (quando a altura do corpo não é relativa aos filhos). Tente mudar bodypara html.
Daan

Aposto que você não verificou sua solução no Iphone porque overflow:hiddennão funciona lá
Shuvo

1

Aqui está a minha solução para parar o pergaminho (sem jQuery). Eu o uso para desativar a rolagem quando o menu lateral aparece.

<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>

Coloquei 17px de preenchimento à direita para compensar o desaparecimento da barra de rolagem. Mas isso também é problemático, principalmente para navegadores móveis. Resolvido obtendo a largura da barra de acordo com este .

Todos juntos nesta caneta.



1

Esta é a solução mais simples que cheguei até agora. E acredite, tentei todos os outros e este é o mais fácil. Ele funciona muito bem em dispositivos Windows , que empurram a página da direita para ter espaço para a barra de rolagem do sistema e dispositivos IOS que não exigem espaço para suas barras de rolagem nos navegadores. Portanto, usando isso, você não precisará adicionar preenchimento à direita para que a página não pisque quando você oculta o excesso de corpo ou html com css .

A solução é bem simples se você pensar bem. A idéia é dar ao window.scrollTop () a mesma posição exata no momento em que um pop-up é aberto. Altere também essa posição quando a janela for redimensionada (pois a posição de rolagem muda assim que isso acontece).

Aqui vamos nos...

Primeiro vamos criar a variável que permitirá que você saiba que o pop-up está aberto e chame-o stopWindowScroll . Se não fizermos isso, você receberá um erro de uma variável indefinida na sua página e a definirá como 0 - como inativo.

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

Agora vamos fazer a função de pop-up aberto, que pode ser qualquer função no seu código que aciona qualquer pop-up que você estiver usando como um plugin ou personalizado. Nesse caso, será um pop-up personalizado simples com um documento simples na função de clique.

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

Portanto, a próxima coisa que fazemos é criar a função pop-up fechada, que repito novamente pode ser qualquer função que você já tenha criado ou esteja usando em um plugin. O importante é que precisamos dessas 2 funções para definir o stopWindowScroll variável como 1 ou 0 para saber quando está aberta ou fechada.

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

Em seguida, vamos criar a função window.scroll para impedir a rolagem uma vez que o stopWindowScroll mencionado acima estiver definido como 1 - como ativo.

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

É isso aí. Não é necessário CSS para que isso funcione, exceto seus próprios estilos para a página. Isso funcionou como um encanto para mim e espero que ajude você e outras pessoas.

Aqui está um exemplo de trabalho no JSFiddle:

Exemplo de JS Fiddle

Deixe-me saber se isso ajudou. Saudações.


1

Armazene o comprimento da rolagem em uma variável global e restaure-o quando necessário!

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

Este código funcionará no Chrome 56 e mais (a resposta original não funciona mais no Chrome).

Usar DomUtils.enableScroll() para ativar a rolagem.

Use DomUtils.disableScroll()para desativar a rolagem.

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

Para evitar o salto, é isso que eu usei

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

e no meu css

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

0

Encontrei esta resposta em outro site :

Desativar rolagem:

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

Após fechar a janela pop-up, role:

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

Isso parece apenas parar a rolagem por toque, mas a rolagem do mouse, as teclas de seta, as teclas de página para cima e para baixo, etc. ainda funcionarão. -1
markasoftware

Esses 'eventos' são para rolagem por toque, basta substituir os eventos que você precisar.
Pennstump

1
Além disso, isso parece ser usado em outra situação muito específica. popupbeforeposition? Para que serve isso? O que isso tem a ver com a desativação temporária da rolagem? Pelo menos torná-lo relevante para esta situação. Parece que você copiou isso diretamente de um site.
Markasoftware

0

A solução de galambalazs é ótima! Funcionou perfeitamente para mim no Chrome e no Firefox. E também pode ser estendido para impedir qualquer evento padrão da janela do navegador. Digamos que você esteja fazendo um aplicativo na tela. Você pode fazer isso:

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

E então, no seu aplicativo, digamos que você processará seus próprios eventos, como mouse, teclado, eventos de toque e assim por diante ... Você pode desativar os eventos padrão quando o mouse entra na tela e reativá-los quando o mouse apaga-se:

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

Você pode até desativar o menu do botão direito com este hack:

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

Eu tive um problema de animação semelhante em telas móveis, mas não em laptops, ao tentar animar uma div usando o comando animar do jquery. Então, decidi usar um timer que restaurava a posição de rolagem da janela com tanta frequência que, a olho nu, o documento pareceria estático. Essa solução funcionou perfeitamente em um dispositivo móvel de tela pequena como o Samsung Galaxy-2 ou iphone-5.

Lógica principal desta abordagem : O cronômetro para definir a posição de rolagem da janela para a posição de rolagem original deve ser iniciado antes do comando jquery animate e, quando a animação for concluída, precisamos limpar esse cronômetro ( original scroll positioné a posição imediatamente antes do início da animação).

Descobri, para minha surpresa agradável, que o documento realmente parecia estático durante a duração da animação, se o intervalo do cronômetro fosse o 1 millisecondque eu estava buscando.

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

Outra solução que funcionou : Com base na resposta de Mohammad Anini nesta postagem para ativar / desativar a rolagem, também descobri que uma versão modificada do código, conforme abaixo, funcionava.

//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

Uma solução simples que funcionou para mim (desativar a rolagem de janela temporariamente).

Com base neste violino: http://jsfiddle.net/dh834zgw/1/

o seguinte snippet (usando jquery) desabilitará a rolagem da janela:

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

E no seu css:

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

Agora, quando você remover o modal, não esqueça de remover a classe noscroll na tag html:

$('html').toggleClass('noscroll');
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.