Wie deaktiviere ich das Scrollen vorübergehend?


434

Ich verwende das scrollTo jQuery-Plugin und möchte wissen, ob es irgendwie möglich ist, das Scrollen im Fensterelement durch Javascript vorübergehend zu deaktivieren. Der Grund, warum ich das Scrollen deaktivieren möchte, ist, dass es wirklich hässlich wird, wenn Sie scrollen, während scrollTo animiert;)

Natürlich könnte ich a machen $("body").css("overflow", "hidden");und es dann wieder auf auto setzen, wenn die Animation stoppt, aber es wäre besser, wenn die Bildlaufleiste noch sichtbar, aber inaktiv wäre.


12
Wenn es immer noch angezeigt wird, wird der Benutzer geschult, zu denken, dass es funktionieren muss. Wenn sich die Dosis nicht bewegt oder nicht reagiert, wird das mentale Modell des Benutzers für die Funktionsweise Ihrer Seite zerstört und es kommt zu Verwirrung. Ich würde einfach eine bessere Möglichkeit finden, mit dem Scrollen während der Animation umzugehen, wie zum Beispiel das Stoppen der Animation.
Marcus Whybrow

Antworten:


731

Die scrollVeranstaltung kann nicht abgesagt werden. Sie können dies jedoch tun, indem Sie die folgenden Interaktionsereignisse abbrechen :
Maus- und Touch-Bildlauf und Schaltflächen Bildlauf mit dem Bildlauf verknüpfte .

[ Arbeitsdemo ]

// 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: Feste Chrome-Desktops und moderne mobile Browser mit passiven Listenern


114
Tipp für andere Entwickler, die in dieser Falle stecken: Stellen Sie sicher, dass Sie alle Aufrufe von 'e.stopPropagation ()' von anderen jQuery-Versuchen entfernen, den Bildlauf zu beenden, da dies nicht nur nicht funktioniert, sondern auch verhindert, dass das Ereignis in DIESEN Code übergeht das funktioniert. Hoffentlich helfen meine verschwendeten 30 Minuten jemand anderem Zeit zu sparen :)
Dirk van Bergen

4
Sie können dem Array mit deaktivierten Schlüsseln 32 (Leerzeichen) hinzufügen (siehe Codekommentare).
Gblazex

14
Ich kann dies wie immer scrollen: mit der mittleren Taste drücken und die Maus bewegen ... Daher wirkt sich dieser Trick nicht auf Benutzer wie mich aus;)
Denis V

11
Die Bildlaufleiste ist nicht deaktiviert.
Verism

8
Dies funktioniert nicht mehr auf Chrome
PerrierCitror

427

Tun Sie es einfach, indem Sie dem Körper eine Klasse hinzufügen:

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

Fügen Sie die Klasse hinzu und entfernen Sie sie, wenn Sie das Scrollen wieder aktivieren möchten, das in IE, FF, Safari und Chrome getestet wurde.

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

Für mobile Geräte müssen Sie dietouchmove Ereignis behandeln:

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

Und lösen Sie die Bindung, um das Scrollen wieder zu aktivieren. Getestet in iOS6 und Android 2.3.3

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

4
Ich habs! Sie müssen das touchmoveEreignis wie bei behandeln $('body').bind('touchmove', function(e){e.preventDefault()}). Diese Antwort wurde bearbeitet, um diese mobile Lösung einzuschließen.
MusikAnimal

3
Cool, muss nur sicherstellen, dass jedes innere Scrollen im Modal für das Touch-Gerät funktioniert. Könnte eine Überlagerung direkt unter dem Modal durchführen und die standardmäßige Berührungsbewegung auf der Überlagerung anstelle des Körpers verhindern.
Hallodom

63
Diese Lösung funktioniert zwar, hat jedoch den (möglicherweise) unerwünschten Effekt, dass Sie zum Anfang der Seite zurückblättern.
Matt

3
Dies funktionierte nicht für mich, es sei denn, mein Selektor war$('body,html')
PickYourPoison

22
Diese Lösung funktioniert, aber die Bildlaufleiste verschwindet und erzeugt einen "Bump" -Effekt (unter Windows OS), wenn Sie diese Klasse auf den Körper anwenden (zum Beispiel)
Georgio

57

Hier ist ein wirklich grundlegender Weg, dies zu tun:

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

In IE6 ist es ziemlich nervös.


14
Nicht wirklich eine Deaktivierung, eher ein Snap-to-Default, wenn der Bildlauf versucht wird.
Marcus Whybrow

11
@Marcus So gut wie es mit einem Ereignis geht, das nicht abgesagt werden kann.
sdleihssirhc

3
Obwohl es es nicht wirklich deaktiviert, simuliert es es und das ist gut genug für mich.
Chris Bier

11
IMHO - beste Antwort hier. Außerdem müssen Sie es nicht sperren, sondern (0, 0)nur die aktuelle Bildlaufposition verwenden.
YemSalat

4
Aber wie können wir es wieder aktivieren?
Kybernetisch

41

Die folgende Lösung ist einfaches, aber reines JavaScript (keine 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 in Safari 7.1 und IE 11. Neueste Chrome, Firefox, Opera ok.
Timo Kähkönen

Immer noch ein bisschen nervös auf dem neuesten Chrome
Jason Allshorn

Funktioniert gut, In Safari, Chrom, flackerte aber in IE
Bhuvan Arora

Wenn diese Lösung für einige Browser nicht funktioniert, dann ist das ein
Browserproblem

Wie in einer anderen Antwort erwähnt, scroll-behavior: smoothborks dies. Ich bin auch nicht damit einverstanden, dass Oto sagt, dass es die Schuld des Browsers ist. Sie gehen im Grunde davon aus, dass etwas sofort passiert, wenn es in Wirklichkeit asynchron ist
Matt Fletcher vor

25

Diese Lösung behält die aktuelle Bildlaufposition bei, während das Bildlauf deaktiviert ist, im Gegensatz zu einigen, bei denen der Benutzer wieder nach oben springt.

Es basiert auf der Antwort von Galambalazs , unterstützt jedoch Touch-Geräte und wurde als einzelnes Objekt mit JQuery Plugin Wrapper überarbeitet.

Demo hier.

Auf Github hier.

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

Ich bin froh, dass es nützlich ist. NB Ich habe mit einem Link dazu im jQuery-Plugin-Format bearbeitet .
Josh Harrison

Könnte helfen, wenn die Schaltfläche zum Deaktivieren des
Bildlaufs

@ user1672694, es funktioniert hier in Chrome. Was ist Ihr Browser und auf welcher Demoseite haben Sie den Fehler gefunden? Irgendwelche JS-Fehler in der Konsole?
Josh Harrison

Unter Chrome (38, Windows 7) kann ich weiterhin scrollen, indem ich auf die mittlere Taste klicke und sie gedrückt halte und dann ziehe.
Sethi

1
Bitte ignorieren Sie, ich fand, dass das Binden mousewheelein Zauber war
Adamj

17

Es tut mir leid, einen alten Beitrag zu beantworten, aber ich habe nach einer Lösung gesucht und bin auf diese Frage gestoßen.

Es gibt viele Problemumgehungen für dieses Problem, um die Bildlaufleiste weiterhin anzuzeigen, z. B. dem Container eine Höhe von 100% und eine overflow-y: scroll Styling zu .

In meinem Fall habe ich gerade ein Div mit einer Bildlaufleiste erstellt, die ich beim Hinzufügen overflow: hiddenzum Body anzeige :

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

Die Element-Bildlaufleiste muss folgende Stile haben:

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

Dies zeigt eine graue Bildlaufleiste, hoffe, es hilft zukünftigen Besuchern.


8

Ich habe nach einer Lösung für dieses Problem gesucht, war aber mit keiner der oben genannten Lösungen zufrieden ( zum Zeitpunkt des Schreibens dieser Antwort ), daher habe ich diese Lösung gefunden.

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

Ich fand, dass dies für mich funktionierte, wenn ich overflow-y: scrollden .scrollDisabledStil hinzufügte . Ansonsten gab es einen kleinen Sprung, da sich die Bildlaufleiste jedes Mal versteckte. Das funktioniert natürlich nur bei mir, weil meine Seite lang genug ist, um auch auf den größten Displays eine Bildlaufleiste zu benötigen.
Andrew Miner

7

Laut dem Beitrag von Galambalaz würde ich Unterstützung für Touch-Geräte hinzufügen, damit wir berühren können, aber nicht nach oben oder unten scrollen:

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

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

3
Sind Sie sicher, dass es sich um eine Antwort handelt, nicht nur um einen Kommentar einer anderen Antwort?
IvanH

6

Ab Chrome 56 und anderen modernen Browsern müssen Sie passive:falseden addEventListenerAnruf ergänzen , damit die preventDefaultArbeit funktioniert. Also benutze ich dies, um das Scrollen auf dem Handy zu beenden:

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

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

5

Nein, ich würde mich nicht für die Ereignisbehandlung entscheiden, weil:

  • Nicht alle Ereignisse erreichen garantiert den Körper.

  • Wenn Sie Text auswählen und nach unten gehen, wird das Dokument gescrollt.

  • Wenn in der Phase des Ereignisses das Ablösen von etw schief geht, sind Sie zum Scheitern verurteilt.

Ich habe mich daran gewöhnt, indem ich eine Aktion zum Kopieren und Einfügen mit einem ausgeblendeten Textbereich ausgeführt habe. Ratet mal, die Seite wird beim Kopieren gescrollt, da ich intern den Textbereich auswählen muss, bevor ich anrufe document.execCommand('copy').

Wie auch immer, so gehe ich vor, beachte setTimeout():

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

Ein Momentum blinkt, wenn die Bildlaufleisten für einen Moment verschwinden, aber es ist akzeptabel, was ich finde.


4

Je nachdem, was Sie mit dem entfernten Bildlauf erreichen möchten, können Sie einfach das Element korrigieren, von dem Sie den Bildlauf entfernen möchten (per Klick oder mit einem anderen Auslöser, den Sie vorübergehend deaktivieren möchten).

Ich suchte nach einer "Temp No Scroll" -Lösung und für meine Bedürfnisse löste dies das Problem

eine Klasse machen

.fixed{
    position: fixed;
}

dann mit 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');
    };
});

Ich fand, dass dies eine ausreichend einfache Lösung ist, die auf allen Browsern gut funktioniert und sich auch auf tragbaren Geräten (z. B. iPhones, Tablets usw.) einfach verwenden lässt. Da das Element vorübergehend fixiert ist, gibt es keine Schriftrolle :)

HINWEIS! Abhängig von der Platzierung Ihres "contentContainer" -Elements müssen Sie es möglicherweise von links anpassen. Dies kann einfach durch Hinzufügen eines CSS-Linkswerts zu diesem Element erfolgen, wenn die feste Klasse aktiv ist

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

Eine andere Lösung:

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

Auf diese Weise haben Sie immer eine vertikale Bildlaufleiste, aber da der größte Teil meines Inhalts länger als das Ansichtsfenster ist, ist dies für mich in Ordnung. Der Inhalt wird mit einem separaten Div zentriert, aber ohne den Rand im Körper erneut festzulegen, würde mein Inhalt links bleiben.

Dies sind die beiden Funktionen, mit denen ich mein Popup / Modal anzeige:

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

Ergebnis: nicht scrollbarer Hintergrund und keine Neupositionierung des Inhalts aufgrund der linken Bildlaufleiste. Getestet mit aktuellem FF, Chrome und IE 10.


Dies funktionierte bei mir und das Problem, nach Verwendung von Position nach oben zu scrollen: behoben. Danke!
Annia Martinez

3

Wie wäre es damit? (Wenn Sie jQuery verwenden)

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

ein bisschen nervös, aber das funktioniert für IE 7 (Client verwendet es). andere Lösungen nicht.
niki b

3

Ich verwende showModalDialog , um die sekundäre Seite als modalen Dialog anzuzeigen .

So blenden Sie die Bildlaufleisten des Hauptfensters aus:

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

und beim Schließen des modalen Dialogfelds werden die Bildlaufleisten des Hauptfensters angezeigt:

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

So greifen Sie über den Dialog auf Elemente im Hauptfenster zu:

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

Nur für alle, die nach showModalDialog suchen : (nach Zeile 29 des Originalcodes)

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

Dies funktionierte für mich in React, wo jQuery nicht vorhanden ist und React keinen Zugriff zum Verwalten des Status des Body-Tags hat.
Jon

3

Das Absagen des Ereignisses wie in der akzeptierten Antwort ist meiner Meinung nach eine schreckliche Methode: /

Stattdessen habe ich position: fixed; top: -scrollTop();unten verwendet.

Demo: https://jsfiddle.net/w9w9hthy/5/

Aus meinem jQuery-Popup-Projekt: 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": ""});
    }
}

Dieser Code berücksichtigt Probleme mit Breite, Höhe, Bildlaufleiste und Seitensprung.

Mögliche Probleme mit dem obigen Code behoben:

  • width, wenn die Position fest eingestellt ist, kann die Breite des HTML-Elements kleiner als 100% sein
  • Höhe wie oben
  • Bildlaufleiste: Wenn die Position festgelegt ist, hat der Seiteninhalt keine Bildlaufleiste mehr, selbst wenn er eine Bildlaufleiste hatte, bevor ein horizontaler Seitensprung ausgeführt wurde
  • Seitensprung: Wenn die Position festgelegt ist, ist der Bildlauf nicht mehr wirksam, was zu einem vertikalen Seitensprung führt

Wenn jemand Verbesserungen am obigen Code zum Einfrieren / Auftauen von Seiten hat, lassen Sie es mich wissen, damit ich diese Verbesserungen meinem Projekt hinzufügen kann.


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
Dies ist hier die beste Lösung.
jfunk

@jfunk zustimmen, einfach und prägnant, kleiner Code, perfekt. Vielen Dank
Florent Roques

2

Ich habe das gleiche Problem. Unten ist die Art und Weise, wie ich damit umgehe.

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

Ich hoffe das hilft.


1

Aufbauend auf der Antwort von Cheyenne Forbes und einer, die ich hier über fcalderan gefunden habe: Deaktiviere einfach die Schriftrolle, verstecke sie nicht? und um Hallodoms Problem zu beheben, dass die Bildlaufleiste verschwindet

CSS:

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

JS:

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

Dieser Code bringt Sie zwar an den Anfang der Seite, aber ich denke, dass der Code von fcalderan eine Problemumgehung hat.


1

Ich weiß, dass dies eine alte Frage ist, aber ich musste etwas sehr Ähnliches tun, und nachdem ich einige Zeit nach einer Antwort gesucht und verschiedene Ansätze ausprobiert hatte, fand ich eine sehr einfache Lösung.

Mein Problem war sehr ähnlich, fast identisch. Der einzige Unterschied besteht darin, dass ich die Bildlaufleiste nicht anzeigen musste. Ich musste nur sicherstellen, dass die Breite weiterhin verwendet wird, damit sich die Seitenbreite nicht ändert, während mein Overlay angezeigt wird .

Wenn ich meine Überlagerung in den Bildschirm schiebe, mache ich Folgendes:

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

und nachdem ich mein Overlay vom Bildschirm geschoben habe, mache ich:

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

WICHTIG: Dies funktioniert perfekt, da meine Überlagerung wann positioniert absoluteist .right: 0pxvisible


1

Die einfachste Methode ist:

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

Um es rückgängig zu machen:

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

Einfach zu implementieren, aber der einzige Nachteil ist:

  • Die Seite springt etwas nach links, wenn sie mittig (horizontal) ausgerichtet ist.

Dies liegt daran, dass die Bildlaufleiste entfernt wird und das Ansichtsfenster etwas breiter wird.


1
das wird die
Bildlaufposition

@AngelDavidCalderaroPacciott Nein, die Bildlaufposition bleibt gleich hoch / entfernt.
Daan

@Daan es setzt die Bildlaufposition auf Chrome zurück
Tom

@ Tom Ich habe es gerade überprüft, es tut es nur in einigen Fällen (wenn die Körpergröße nicht relativ zu seinen Kindern ist). Bitte versuchen Sie es zu ändern , bodyum htmlstatt.
Daan

Ich wette, Sie haben Ihre Lösung im Iphone nicht überprüft, da overflow:hiddensie dort nicht funktioniert
Shuvo

1

Hier ist meine Lösung, um den Bildlauf zu stoppen (keine jQuery). Ich benutze es, um den Bildlauf zu deaktivieren, wenn das Seitenmenü angezeigt wird.

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

Ich habe 17 Pixel Polsterung nach rechts gesetzt, um das Verschwinden der Bildlaufleiste zu kompensieren. Dies ist jedoch auch problematisch, vor allem für mobile Browser. Gelöst, indem die Balkenbreite entsprechend ermittelt wird .

Alles zusammen in diesem Stift.



1

Dies ist die einfachste Lösung, die ich bisher bekommen habe. Und glauben Sie mir, ich habe alle anderen ausprobiert und dies ist die einfachste. Es funktioniert hervorragend auf Windows-Geräten , bei denen die Seite von rechts verschoben wird, um Platz für die System-Bildlaufleiste und für iOS-Geräte zu haben, die keinen Platz für ihre Bildlaufleisten in den Browsern benötigen. Wenn Sie dies verwenden, müssen Sie rechts keine Auffüllungen hinzufügen, damit die Seite nicht flackert, wenn Sie den Überlauf des Körpers oder HTML mit CSS verbergen .

Die Lösung ist ziemlich einfach, wenn Sie darüber nachdenken. Die Idee ist, das window.scrollTop () zu geben genau die Position zu geben, an der ein Popup geöffnet wird. Ändern Sie diese Position auch, wenn die Größe des Fensters geändert wird (da sich die Bildlaufposition ändert, sobald dies geschieht).

Auf geht's...

Erstellen Sie zunächst die Variable, die Sie darüber informiert, dass das Popup geöffnet ist, und rufen Sie stopWindowScroll auf . Wenn wir dies nicht tun, erhalten Sie einen Fehler einer undefinierten Variablen auf Ihrer Seite und setzen sie auf 0 - als nicht aktiv.

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

Lassen Sie uns jetzt die Popup-Funktion öffnen, die eine beliebige Funktion in Ihrem Code sein kann, die jedes Popup auslöst, das Sie als Plugin oder benutzerdefiniert verwenden. In diesem Fall handelt es sich um ein einfaches benutzerdefiniertes Popup mit einer einfachen Funktion zum Klicken auf Dokumente.

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

Als nächstes erstellen wir die Funktion zum Schließen des Popups, die ich noch einmal wiederhole. Dies kann jede Funktion sein, die Sie bereits erstellt haben oder die Sie in einem Plugin verwenden. Wichtig ist, dass wir diese beiden Funktionen benötigen, um die Variable stopWindowScroll auf 1 oder 0 zu setzen und zu wissen, wann sie geöffnet oder geschlossen ist.

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

Lassen Sie uns dann die window.scroll-Funktion erstellen, damit wir das Scrollen verhindern können, sobald der oben erwähnte stopWindowScroll auf 1 gesetzt ist - als aktiv.

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

Das ist es. Damit dies funktioniert, ist kein CSS erforderlich, außer Ihren eigenen Stilen für die Seite. Das hat mir sehr gut gefallen und ich hoffe, es hilft Ihnen und anderen.

Hier ist ein Arbeitsbeispiel für JSFiddle:

JS Fiddle Beispiel

Lassen Sie mich wissen, ob dies geholfen hat. Grüße.


1

Speichern Sie die Bildlauflänge in einer globalen Variablen und stellen Sie sie bei Bedarf wieder her!

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

Dieser Code funktioniert unter Chrome 56 und höher (die ursprüngliche Antwort funktioniert unter Chrome nicht mehr).

Verwenden Sie DomUtils.enableScroll()diese Option , um das Scrollen zu aktivieren.

Verwenden Sie DomUtils.disableScroll()diese Option, um das Scrollen zu deaktivieren.

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

Um den Sprung zu verhindern, habe ich dies verwendet

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

und in meinem css

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

0

Ich habe diese Antwort auf einer anderen Seite gefunden :

Bildlauf deaktivieren:

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

Nach dem Schließen der Popup-Freigabe scrollen:

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

Das scheint nur das Scrollen mit der Berührung zu stoppen, aber das Scrollen mit der Maus, die Pfeiltasten, die Auf- und Ab-Tasten usw. funktionieren weiterhin. -1
Markasoftware

Diese "Ereignisse" dienen zum Scrollen durch Berühren. Ersetzen Sie einfach alle Ereignisse, die Sie benötigen.
Pennstump

1
Dies scheint auch in einer anderen sehr spezifischen Situation verwendet zu werden. popupbeforeposition? Wofür soll das sein? Was hat dies mit der vorübergehenden Deaktivierung des Bildlaufs zu tun? Machen Sie es zumindest für diese Situation relevant. Es sieht so aus, als hätten Sie dies direkt von einer Website kopiert.
Markasoftware

0

Die Lösung von Galambalazs ist großartig! Es hat sowohl in Chrome als auch in Firefox perfekt für mich funktioniert. Es kann auch erweitert werden, um ein Standardereignis im Browserfenster zu verhindern. Angenommen, Sie erstellen eine App auf der Leinwand. Sie könnten dies tun:

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

Nehmen wir dann an, Sie verarbeiten in Ihrer App Ihre eigenen Ereignisse wie Maus, Tastatur, Berührungsereignisse usw. Sie können Standardereignisse deaktivieren, wenn sich die Maus in der Zeichenfläche befindet, und sie wieder aktivieren, wenn Sie mit der Maus arbeiten geht raus:

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

Sie können mit diesem Hack sogar das Rechtsklick-Menü deaktivieren:

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

Ich hatte ein ähnliches Animationsproblem auf mobilen Bildschirmen, aber nicht auf Laptops, als ich versuchte, ein Div mit dem Befehl animieren von jquery zu animieren. Deshalb habe ich mich für einen Timer entschieden, der die Bildlaufposition des Fensters so häufig wiederherstellt, dass das Dokument mit bloßem Auge statisch erscheint. Diese Lösung funktionierte perfekt auf mobilen Geräten mit kleinem Bildschirm wie Samsung Galaxy-2 oder iPhone-5.

Hauptlogik dieses Ansatzes : Der Timer zum Festlegen der Bildlaufposition des Fensters auf die ursprüngliche Bildlaufposition sollte vor dem Befehl jquery animate gestartet werden. Wenn die Animation abgeschlossen ist, müssen wir diesen Timer löschen ( original scroll positionist die Position unmittelbar vor dem Start der Animation).

Zu meiner angenehmen Überraschung stellte ich fest, dass das Dokument während der Animationsdauer tatsächlich statisch erschien, wenn das Timer-Intervall war 1 millisecond, was ich anstrebte.

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

EINE ANDERE LÖSUNG, die funktioniert hat : Basierend auf der Antwort von Mohammad Anini in diesem Beitrag zum Aktivieren / Deaktivieren des Bildlaufs habe ich auch festgestellt, dass eine modifizierte Version des Codes wie unten funktioniert.

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

Eine einfache Lösung, die für mich funktioniert hat (Deaktivieren des Fenster-Bildlaufs vorübergehend).

Basierend auf dieser Geige: http://jsfiddle.net/dh834zgw/1/

Das folgende Snippet (mit jquery) deaktiviert den Fensterlauf:

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

Und in Ihrem CSS:

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

Vergessen Sie beim Entfernen des Modals nicht, die Noscroll-Klasse im HTML-Tag zu entfernen:

$('html').toggleClass('noscroll');
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.