Zapobiec przewijaniu elementu nadrzędnego, gdy pozycja przewijania elementu wewnętrznego sięga góry / dołu? [duplikat]

to pytanie ma już odpowiedzi tutaj : zapobiegaj bąbelkom przewijania z elementu do okna (15 odpowiedzi) Zamknięty 2 lata temu .

Mam małą "pływającą skrzynkę narzędziową" - div z position:fixed; overflow:auto. Działa dobrze.

Ale podczas przewijania wewnątrz tego pola (za pomocą kółka myszy)i dotarcia do dołu lub góry, element nadrzędny "przejmuje ""żądanie przewijania": dokument za skrzynką narzędzi przewija.
- Co jest irytujące, a nie to, o co użytkownik "prosił".

Używam jQuery i pomyślałem, że mogę zatrzymać to zachowanie z wydarzenie.stopropagacja():
$("#toolBox").scroll( function(event){ event.stoppropagation() });

Nie jest to jednak możliwe, ponieważ nie jest to możliwe.]} - Zaskakująco trudno jest szukać tego tematu NA SO (I Google), więc muszę zapytać:
Jak zapobiec propagacji / bulgotaniu zdarzenia przewijania ?

Edit:
Rozwiązanie pracy dzięki amustill (i Brandon Aaron za mousewheel-plugin here:
https://github.com/brandonaaron/jquery-mousewheel/raw/master/jquery.mousewheel.js{[6]

$(".ToolPage").bind('mousewheel', function(e, d)  
    var t = $(this);
    if (d > 0 && t.scrollTop() === 0) {
        e.preventDefault();
    }
    else {
        if (d < 0 && (t.scrollTop() == t.get(0).scrollHeight - t.innerHeight())) {
            e.preventDefault();
        }
    }
});
Author: Pandaiolo, 2011-04-27

30 answers

Jest to możliwe za pomocą wtyczki Mousewheel Brandona Aarona.

Oto demo: http://jsbin.com/jivutakama/edit?html, js, output

 44
Author: amustill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-01 22:23:40

Dodaję tę odpowiedź dla kompletności, ponieważ zaakceptowana odpowiedź przez @ amustill nie rozwiązuje poprawnie problemu w Internet Explorerze . Proszę zobaczyć komentarze w mój oryginalny post Po szczegóły. Ponadto rozwiązanie to nie wymaga żadnych wtyczek - tylko jQuery.

W istocie kod działa poprzez obsługę zdarzenia mousewheel. Każde takie zdarzenie zawiera wheelDelta równe liczbie px, na którą przesunie przewijany obszar. Jeśli wartość ta jest >0, Następnie przewijamy up. Jeśli wheelDelta jest <0 to przewijamy down.

FireFox : FireFox używa DOMMouseScroll jako zdarzenia i zapełnia originalEvent.detail, którego +/- jest odwrócone od tego, co opisano powyżej. Zwykle zwraca interwały 3, podczas gdy inne przeglądarki zwracają przewijanie w interwałach 120 (przynajmniej na moim komputerze). Aby poprawić, po prostu wykrywamy go i mnożymy przez -40, aby znormalizować.

@odpowiedź amustilla działa poprzez anulowanie Zdarzenie, jeśli obszar przewijania <div> znajduje się już w górnej lub dolnej maksymalnej pozycji. Jednak Internet Explorer ignoruje odwołane wydarzenie w sytuacjach, gdy delta jest większy niż pozostała przestrzeń przewijalna.

Innymi słowy, jeśli masz 200px wysoki <div> zawierający 500px przewijalnej zawartości, a bieżącym scrollTop jest 400, Zdarzenie mousewheel, które każe przeglądarce przewijać 120px dalej, spowoduje zarówno <div>, jak i <body> przewijanie, ponieważ 400 + 120 > 500.

Tak więc-aby rozwiązać problem, musimy zrobić coś nieco innego, jak pokazano poniżej:]}

Wymagany jQuery kod to:

$(document).on('DOMMouseScroll mousewheel', '.Scrollable', function(ev) {
    var $this = $(this),
        scrollTop = this.scrollTop,
        scrollHeight = this.scrollHeight,
        height = $this.innerHeight(),
        delta = (ev.type == 'DOMMouseScroll' ?
            ev.originalEvent.detail * -40 :
            ev.originalEvent.wheelDelta),
        up = delta > 0;

    var prevent = function() {
        ev.stopPropagation();
        ev.preventDefault();
        ev.returnValue = false;
        return false;
    }

    if (!up && -delta > scrollHeight - height - scrollTop) {
        // Scrolling down, but this will take us past the bottom.
        $this.scrollTop(scrollHeight);
        return prevent();
    } else if (up && delta > scrollTop) {
        // Scrolling up, but this will take us past the top.
        $this.scrollTop(0);
        return prevent();
    }
});

W istocie kod ten anuluje każde zdarzenie przewijania, które utworzyłoby niechciany warunek krawędzi, a następnie używa jQuery, aby ustawić scrollTop z <div> na maksymalną lub minimalną wartość, w zależności od kierunku, w którym zdarzenie mousewheel było żądane.

Ponieważ impreza jest odwołana w obu przypadkach, nigdy nie propaguje się do body w ogóle, a zatem rozwiązuje problem w IE, jak również wszystkich innych przeglądarkach.

Umieściłem również działający przykład na jsFiddle .

 171
Author: Troy Alford,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:01

Wszystkie rozwiązania podane w tym wątku nie wspominają o istniejącym i natywnym sposobie rozwiązania tego problemu bez zmiany kolejności DOM i / lub użycia sztuczek zapobiegających zdarzeniom. Ale jest dobry powód: ten sposób jest zastrzeżony - i dostępny tylko na platformie MS web. Cytowanie MSDN:

-ms-scroll-chaining właściwość-określa zachowanie przewijania, które występuje, gdy użytkownik przekroczy limit przewijania podczas manipulacji. Nieruchomość wartości:

Przykuta - Wartość początkowa. Najbliższy przewijalny element nadrzędny rozpoczyna przewijanie, gdy użytkownik przekroczy limit przewijania podczas manipulacji. Nie ma efektu odbicia.

None - efekt odbicia jest wyświetlany, gdy użytkownik przekroczy limit przewijania podczas manipulacji.

Przyznane, ta właściwość jest obsługiwana tylko w IE10 + / Edge. Mimo to, oto telling quote:

Aby dać ci poczucie, jak popularne jest przewijanie chaining może być, opinie i recenzje na temat my quick http-archive search "-ms-scroll-chaining: brak" jest używany w 0.4% top 300K stron, mimo że jest ograniczony w funkcjonalność i obsługiwana tylko w IE / Edge.

A teraz dobra wiadomość, wszyscy! Począwszy od Chrome 63, wreszcie mamy natywne lekarstwo dla platform opartych na Blink - i to zarówno Chrome (oczywiście) i Android WebView (wkrótce).

Cytowanie artykuł wprowadzający:

The overscroll-behavior właściwość jest nową funkcją CSS, która kontroluje zachowanie tego, co dzieje się po przewróceniu kontenera (łącznie z samą stroną). Możesz go użyć do anulowania łańcucha przewijania, wyłącz/dostosuj akcję pull-to-refresh, wyłącz rubberbanding efekty na iOS (gdy Safari implementuje overscroll-behavior), i więcej.[...]

Właściwość przyjmuje trzy możliwe wartości:

Auto - Domyślnie. Zwoje pochodzące od pierwiastka mogą się rozmnażać na elementy przodków.

Contain - zapobiega wiązaniu zwojów. Zwoje nie propagować do przodków, ale lokalne efekty w obrębie węzła są pokazane. Na przykład efekt poświaty overscroll na Androidzie lub efekt rubberbanding na iOS, który powiadamia użytkownika, gdy uderzył w granica przewijania. Notatka: using overscroll-behavior: contain on the html element zapobiega nadmiernym akcjom nawigacyjnym.

None - tak samo jak contain, ale również zapobiega efektom overscroll wewnątrz sam węzeł (np. Android overscroll glow lub iOS rubberbanding).

[...] najlepsze jest to, że używanie overscroll-behavior nie powoduje negatywnych wpływaj na wydajność strony, jak hacki wspomniane we wstępie!

Oto to funkcja w akcji. A oto odpowiedni dokument modułu CSS.

Aktualizacja: Firefox, od wersji 59, dołączył do klubu, a MS Edge ma zaimplementować tę funkcję w wersji 18. Oto odpowiedni caniusage.

 33
Author: raina77ow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Wiem, że to dość stare pytanie, ale ponieważ jest to jeden z najlepszych wyników w google... Musiałem jakoś anulować scroll bubbling bez jQuery i ten kod MI działa:

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

document.getElementById('a').onmousewheel = function(e) { 
  document.getElementById('a').scrollTop -= e. wheelDeltaY; 
  preventDefault(e);
}
 24
Author: Nebril,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-20 11:58:05

EDIT: CodePen example

Dla AngularJS zdefiniowałem następującą dyrektywę:

module.directive('isolateScrolling', function () {
  return {
    restrict: 'A',
      link: function (scope, element, attr) {
        element.bind('DOMMouseScroll', function (e) {
          if (e.detail > 0 && this.clientHeight + this.scrollTop == this.scrollHeight) {
            this.scrollTop = this.scrollHeight - this.clientHeight;
            e.stopPropagation();
            e.preventDefault();
            return false;
          }
          else if (e.detail < 0 && this.scrollTop <= 0) {
            this.scrollTop = 0;
            e.stopPropagation();
            e.preventDefault();
            return false;
          }
        });
        element.bind('mousewheel', function (e) {
          if (e.deltaY > 0 && this.clientHeight + this.scrollTop >= this.scrollHeight) {
            this.scrollTop = this.scrollHeight - this.clientHeight;
            e.stopPropagation();
            e.preventDefault();
            return false;
          }
          else if (e.deltaY < 0 && this.scrollTop <= 0) {
            this.scrollTop = 0;
            e.stopPropagation();
            e.preventDefault();
            return false;
          }

          return true;
        });
      }
  };
});

A następnie dodano go do elementu przewijalnego (menu rozwijane ul):

<div class="dropdown">
  <button type="button" class="btn dropdown-toggle">Rename <span class="caret"></span></button>
  <ul class="dropdown-menu" isolate-scrolling>
    <li ng-repeat="s in savedSettings | objectToArray | orderBy:'name' track by s.name">
      <a ng-click="renameSettings(s.name)">{{s.name}}</a>
    </li>
  </ul>
</div>

Testowane na Chrome i Firefox. Płynne przewijanie Chrome pokonuje ten hack, gdy duży ruch koła myszy jest wykonany w pobliżu (ale nie w) górnej lub dolnej części obszaru przewijania.

 19
Author: dOxxx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-20 14:19:22

Jest mnóstwo takich pytań, z wieloma odpowiedziami, ale nie mogłem znaleźć satysfakcjonującego rozwiązania, które nie obejmowałoby zdarzeń, skryptów, wtyczek itp. Chciałem zachować to prosto w HTML i CSS. W końcu znalazłem rozwiązanie, które zadziałało, chociaż wymagało to restrukturyzacji znaczników, aby przerwać łańcuch zdarzeń.


1. Podstawowy problem

Wejście przewijania (np.: mousewheel) zastosowane do elementu modalnego rozleje się na element nadrzędny i przewiń go w tym samym kierunku, jeśli jakiś taki element jest przewijalny:

(wszystkie przykłady mają być wyświetlane w rozdzielczościach pulpitu)

Https://jsfiddle.net/ybkbg26c/5/

HTML:

<div id="parent">
  <div id="modal">
    This text is pretty long here.  Hope fully, we will get some scroll bars.
  </div>
</div>

CSS:

#modal {
  position: absolute;
  height: 100px;
  width: 100px;
  top: 20%;
  left: 20%;
  overflow-y: scroll;
}
#parent {
  height: 4000px;
}

2. No parent scroll on modal scroll

Powodem, dla którego przodek kończy przewijanie jest to, że zdarzenie przewijania i jakiś element w łańcuchu jest w stanie obsłużyć to. Sposób, aby to powstrzymać jest upewnienie się, że żaden z elementów na łańcuchu nie wie, jak obsługiwać zwój. W naszym przykładzie możemy refaktorować drzewo, aby przenieść modal Z elementu nadrzędnego. Z niejasnych powodów nie wystarczy zachować rodzica i rodzeństwo modalnego DOM; rodzic musi być owinięty innym elementem, który ustanawia nowy kontekst układania. Idealnie umiejscowiona owijka wokół rodzica może załatwić sprawę.

Otrzymujemy wynik, że dopóki modal otrzymuje Zdarzenie przewijania, zdarzenie nie będzie bąbelkowe do elementu "rodzic".

Zazwyczaj powinno być możliwe przeprojektowanie drzewa DOM w celu obsługi tego zachowania bez wpływu na to, co widzi użytkownik końcowy.

Https://jsfiddle.net/0bqq31Lv/3/

HTML:

<div id="context">
  <div id="parent">
  </div>
</div>
<div id="modal">
  This text is pretty long here.  Hope fully, we will get some scroll bars.
</div>

CSS (tylko nowy):

#context {
  position: absolute;
  overflow-y: scroll;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

3. Brak przewijania w dowolnym miejscu z wyjątkiem modalnego, gdy jest włączony

Powyższe rozwiązanie pozwala rodzicowi na odbieranie zdarzeń przewijania, o ile są nie jest przechwytywany przez okno modalne (tzn. jeżeli zostanie uruchomiony przez kółko myszy, gdy kursor nie znajduje się nad modalem). Jest to czasami niepożądane i możemy zabronić przewijania tła, gdy modal jest w górę. Aby to zrobić, musimy wstawić dodatkowy kontekst układania, który obejmuje cały viewport za modalem. Możemy to zrobić wyświetlając absolutnie pozycjonowaną nakładkę, która w razie potrzeby może być w pełni przezroczysta (ale nie visibility:hidden).

Https://jsfiddle.net/0bqq31Lv/2/

HTML:

<div id="context">
  <div id="parent">
  </div>
</div>
<div id="overlay">  
</div>
<div id="modal">
  This text is pretty long here.  Hope fully, we will get some scroll bars.
</div>

CSS (nowy na górze #2):

#overlay {
  background-color: transparent;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
 13
Author: Daniel S.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-24 10:12:17

Jako wariant, aby uniknąć problemów z wydajnością przy obsłudze scroll lub mousewheel, możesz użyć kodu jak poniżej:

Css:

body.noscroll {
    overflow: hidden;
}
.scrollable {
    max-height: 200px;
    overflow-y: scroll;
    border: 1px solid #ccc;
}

Html:

<div class="scrollable">
...A bunch of items to make the div scroll...
</div>
...A bunch of text to make the body scroll...

Js:

var $document = $(document),
    $body = $('body'),
    $scrolable = $('.scrollable');

$scrolable.on({
          'mouseenter': function () {
            // add hack class to prevent workspace scroll when scroll outside
            $body.addClass('noscroll');
          },
          'mouseleave': function () {
            // remove hack class to allow scroll
            $body.removeClass('noscroll');
          }
        });

Przykład pracy: http://jsbin.com/damuwinarata/4

 9
Author: Bohdan Lyzanets,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-10 14:33:52

Oto prosta wersja JavaScript:

function scroll(e) {
  var delta = (e.type === "mousewheel") ? e.wheelDelta : e.detail * -40;
  if (delta < 0 && (this.scrollHeight - this.offsetHeight - this.scrollTop) <= 0) {
    this.scrollTop = this.scrollHeight;
    e.preventDefault();
  } else if (delta > 0 && delta > this.scrollTop) {
    this.scrollTop = 0;
    e.preventDefault();
  }
}
document.querySelectorAll(".scroller").addEventListener("mousewheel", scroll);
document.querySelectorAll(".scroller").addEventListener("DOMMouseScroll", scroll);
 9
Author: silverwind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-19 00:01:13

Angular Js Directive

/ Align = "left" / Poniżej znajduje się zestaw innych odpowiedzi tutaj. testowane na Chrome i Internet Explorer 11.
var app = angular.module('myApp');

app.directive("preventParentScroll", function () {
    return {
        restrict: "A",
        scope: false,
        link: function (scope, elm, attr) {
            elm.bind('mousewheel', onMouseWheel);
            function onMouseWheel(e) {
                elm[0].scrollTop -= (e.wheelDeltaY || (e.originalEvent && (e.originalEvent.wheelDeltaY || e.originalEvent.wheelDelta)) || e.wheelDelta || 0);
                e.stopPropagation();
                e.preventDefault();
                e.returnValue = false;
            }
        }
    }
});

Użycie

<div prevent-parent-scroll>
    ...
</div>

Ma nadzieję, że pomoże to następnej osobie, która dotrze tutaj z wyszukiwarki Google.

 9
Author: Jossef Harush,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-15 11:37:55

Użycie natywnych właściwości przewijania elementów z wartością delta z wtyczki mousewheel:

$elem.on('mousewheel', function (e, delta) {
    // Restricts mouse scrolling to the scrolling range of this element.
    if (
        this.scrollTop < 1 && delta > 0 ||
        (this.clientHeight + this.scrollTop) === this.scrollHeight && delta < 0
    ) {
        e.preventDefault();
    }
});
 7
Author: Pete B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-19 12:55:34

W przypadku, gdy ktoś nadal szuka rozwiązania dla tego, poniższy plugin wykonuje zadanie http://mohammadyounes.github.io/jquery-scrollLock/

W pełni rozwiązuje problem blokowania przewijania kółka myszy wewnątrz danego kontenera, zapobiegając jego rozprzestrzenianiu się do elementu nadrzędnego.

Nie zmienia prędkości przewijania kół, nie wpłynie to na wrażenia użytkownika. i masz takie samo zachowanie niezależnie od prędkości przewijania w pionie kółka myszy OS (w systemie Windows można go ustawić na jeden ekran lub jedną linię do 100 linii na wycięcie).

Demo: http://mohammadyounes.github.io/jquery-scrollLock/example/

Źródło: https://github.com/MohammadYounes/jquery-scrollLock

 6
Author: MK.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-24 12:47:17

ODPOWIEDŹ na nokaut:

ko.bindingHandlers.preventParentScroll = {
    init: function (element, valueAccessor, allBindingsAccessor, context) {
        $(element).mousewheel(function (e, d) {
            var t = $(this);
            if (d > 0 && t.scrollTop() === 0) {
                e.preventDefault();
            }
            else {
                if (d < 0 && (t.scrollTop() == t.get(0).scrollHeight - t.innerHeight())) {
                    e.preventDefault();
                }
            }
        });
    }
};
 4
Author: mhu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-18 14:45:23

Powyższa metoda nie jest taka naturalna, po jakimś googlowaniu znajduję ładniejsze rozwiązanie i nie ma potrzeby używania jQuery. Zob. [1] i demo [2].

  var element = document.getElementById('uf-notice-ul');

  var isMacWebkit = (navigator.userAgent.indexOf("Macintosh") !== -1 &&
    navigator.userAgent.indexOf("WebKit") !== -1);
  var isFirefox = (navigator.userAgent.indexOf("firefox") !== -1);

  element.onwheel = wheelHandler; // Future browsers
  element.onmousewheel = wheelHandler; // Most current browsers
  if (isFirefox) {
    element.scrollTop = 0;
    element.addEventListener("DOMMouseScroll", wheelHandler, false);
  }
  // prevent from scrolling parrent elements
  function wheelHandler(event) {
    var e = event || window.event; // Standard or IE event object

    // Extract the amount of rotation from the event object, looking
    // for properties of a wheel event object, a mousewheel event object 
    // (in both its 2D and 1D forms), and the Firefox DOMMouseScroll event.
    // Scale the deltas so that one "click" toward the screen is 30 pixels.
    // If future browsers fire both "wheel" and "mousewheel" for the same
    // event, we'll end up double-counting it here. Hopefully, however,
    // cancelling the wheel event will prevent generation of mousewheel.
    var deltaX = e.deltaX * -30 || // wheel event
      e.wheelDeltaX / 4 || // mousewheel
      0; // property not defined
    var deltaY = e.deltaY * -30 || // wheel event
      e.wheelDeltaY / 4 || // mousewheel event in Webkit
      (e.wheelDeltaY === undefined && // if there is no 2D property then 
        e.wheelDelta / 4) || // use the 1D wheel property
      e.detail * -10 || // Firefox DOMMouseScroll event
      0; // property not defined

    // Most browsers generate one event with delta 120 per mousewheel click.
    // On Macs, however, the mousewheels seem to be velocity-sensitive and
    // the delta values are often larger multiples of 120, at 
    // least with the Apple Mouse. Use browser-testing to defeat this.
    if (isMacWebkit) {
      deltaX /= 30;
      deltaY /= 30;
    }
    e.currentTarget.scrollTop -= deltaY;
    // If we ever get a mousewheel or wheel event in (a future version of)
    // Firefox, then we don't need DOMMouseScroll anymore.
    if (isFirefox && e.type !== "DOMMouseScroll") {
      element.removeEventListener("DOMMouseScroll", wheelHandler, false);
    }
    // Don't let this event bubble. Prevent any default action.
    // This stops the browser from using the mousewheel event to scroll
    // the document. Hopefully calling preventDefault() on a wheel event
    // will also prevent the generation of a mousewheel event for the
    // same rotation.
    if (e.preventDefault) e.preventDefault();
    if (e.stopPropagation) e.stopPropagation();
    e.cancelBubble = true; // IE events
    e.returnValue = false; // IE events
    return false;
  }

[1] https://dimakuzmich.wordpress.com/2013/07/16/prevent-scrolling-of-parent-element-with-javascript/

[2] http://jsfiddle.net/dima_k/5mPkB/1/

 4
Author: jinwei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-24 09:44:20

To działa w AngularJS. Testowane na Chrome i Firefox.

.directive('stopScroll', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            element.bind('mousewheel', function (e) {
                var $this = $(this),
                    scrollTop = this.scrollTop,
                    scrollHeight = this.scrollHeight,
                    height = $this.height(),
                    delta = (e.type == 'DOMMouseScroll' ?
                    e.originalEvent.detail * -40 :
                        e.originalEvent.wheelDelta),
                    up = delta > 0;

                var prevent = function() {
                    e.stopPropagation();
                    e.preventDefault();
                    e.returnValue = false;
                    return false;
                };

                if (!up && -delta > scrollHeight - height - scrollTop) {
                    // Scrolling down, but this will take us past the bottom.
                    $this.scrollTop(scrollHeight);
                    return prevent();
                } else if (up && delta > scrollTop) {
                    // Scrolling up, but this will take us past the top.
                    $this.scrollTop(0);
                    return prevent();
                }
            });
        }
    };
})
 4
Author: Remot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 19:32:59

Mój plugin jQuery:

$('.child').dontScrollParent();

$.fn.dontScrollParent = function()
{
    this.bind('mousewheel DOMMouseScroll',function(e)
    {
        var delta = e.originalEvent.wheelDelta || -e.originalEvent.detail;

        if (delta > 0 && $(this).scrollTop() <= 0)
            return false;
        if (delta < 0 && $(this).scrollTop() >= this.scrollHeight - $(this).height())
            return false;

        return true;
    });
}
 2
Author: psycho brm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-14 14:28:28

Mam podobną sytuację i oto jak ją rozwiązałem:
Wszystkie moje przewijalne elementy otrzymują klasę scrollable .

$(document).on('wheel', '.scrollable', function(evt) {
  var offsetTop = this.scrollTop + parseInt(evt.originalEvent.deltaY, 10);
  var offsetBottom = this.scrollHeight - this.getBoundingClientRect().height - offsetTop;

  if (offsetTop < 0 || offsetBottom < 0) {
    evt.preventDefault();
  } else {
    evt.stopImmediatePropagation();
  }
});

stopImmediatePropagation () upewnia się, że nie przewija przewijalnego obszaru nadrzędnego z przewijalnego obszaru podrzędnego.

Oto waniliowa implementacja JS: http://jsbin.com/lugim/2/edit?js, output

 2
Author: user3259967,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-21 15:06:49

Nowy Web dev tutaj. To działało jak urok dla mnie zarówno na IE, jak i Chrome.

static preventScrollPropagation(e: HTMLElement) {
    e.onmousewheel = (ev) => {
        var preventScroll = false;
        var isScrollingDown = ev.wheelDelta < 0;
        if (isScrollingDown) {
            var isAtBottom = e.scrollTop + e.clientHeight == e.scrollHeight;
            if (isAtBottom) {
                preventScroll = true;
            }
        } else {
            var isAtTop = e.scrollTop == 0;
            if (isAtTop) {
                preventScroll = true;
            }
        }
        if (preventScroll) {
            ev.preventDefault();
        }
    }
}

Nie daj się zwieść liczbie linii, jest to dość proste - tylko trochę zwięzłe dla czytelności (samodokumentujący kod FTW prawda?)

Powinienem również wspomnieć, że językiem tutaj jest TypeScript , ale jak zawsze, łatwo jest przekonwertować go do JS.

 2
Author: Vivek Maharajh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-25 16:52:25

Dla tych, którzy używają MooTools, oto równoważny kod:

            'mousewheel': function(event){
            var height = this.getSize().y;
            height -= 2;    // Not sure why I need this bodge
            if ((this.scrollTop === (this.scrollHeight - height) && event.wheel < 0) || 
                (this.scrollTop === 0 && event.wheel > 0)) {
                event.preventDefault();
            }

Należy pamiętać, że ja, podobnie jak inni, musiałem poprawić wartość o kilka px, do tego służy height - = 2.

Zasadniczo główną różnicą jest to, że w MooTools informacje delta pochodzą od zdarzenia.koła zamiast dodatkowego parametru przekazanego do zdarzenia.

Ponadto miałem problemy, jeśli powiązałem ten kod z czymkolwiek (event.cel.przewijanie dla funkcji bound nie jest takie samo.scrollHeight for a niezwiązany)

Mam nadzieję, że to komuś pomoże tak samo jak ten post pomógł mi;)

 1
Author: Clive Galway,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-11 12:31:50

Zobacz kod Lelanda Kwonga.

Podstawową ideą jest powiązanie zdarzenia wheeling z elementem potomnym, a następnie użycie natywnej właściwości javascript scrollHeight i właściwości jquery outerHeight elementu potomnego do wykrycia końca przewijania, na którym return false do zdarzenia wheeling, aby zapobiec przewijaniu.

var scrollableDist,curScrollPos,wheelEvent,dY;
$('#child-element').on('wheel', function(e){
  scrollableDist = $(this)[0].scrollHeight - $(this).outerHeight();
  curScrollPos = $(this).scrollTop();
  wheelEvent = e.originalEvent;
  dY = wheelEvent.deltaY;
  if ((dY>0 && curScrollPos >= scrollableDist) ||
      (dY<0 && curScrollPos <= 0)) {
    return false;
  }
});
 1
Author: Vic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-28 13:44:21

Skopiowałem to z wybranej biblioteki: https://github.com/harvesthq/chosen/blob/master/coffee/chosen.jquery.coffee

function preventParentScroll(evt) {
    var delta = evt.deltaY || -evt.wheelDelta || (evt && evt.detail)
    if (delta) {
        evt.preventDefault()
        if (evt.type ==  'DOMMouseScroll') {
            delta = delta * 40  
        }
        fakeTable.scrollTop = delta + fakeTable.scrollTop
    }
}
var el = document.getElementById('some-id')
el.addEventListener('mousewheel', preventParentScroll)
el.addEventListener('DOMMouseScroll', preventParentScroll)
To mi pasuje.
 1
Author: Drew LeSueur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-27 10:42:55

JQuery plugin z emulacją naturalnego przewijania dla Internet Explorera

  $.fn.mousewheelStopPropagation = function(options) {
    options = $.extend({
        // defaults
        wheelstop: null // Function
        }, options);

    // Compatibilities
    var isMsIE = ('Microsoft Internet Explorer' === navigator.appName);
    var docElt = document.documentElement,
        mousewheelEventName = 'mousewheel';
    if('onmousewheel' in docElt) {
        mousewheelEventName = 'mousewheel';
    } else if('onwheel' in docElt) {
        mousewheelEventName = 'wheel';
    } else if('DOMMouseScroll' in docElt) {
        mousewheelEventName = 'DOMMouseScroll';
    }
    if(!mousewheelEventName) { return this; }

    function mousewheelPrevent(event) {
        event.preventDefault();
        event.stopPropagation();
        if('function' === typeof options.wheelstop) {
            options.wheelstop(event);
        }
    }

    return this.each(function() {
        var _this = this,
            $this = $(_this);
        $this.on(mousewheelEventName, function(event) {
            var origiEvent = event.originalEvent;
            var scrollTop = _this.scrollTop,
                scrollMax = _this.scrollHeight - $this.outerHeight(),
                delta = -origiEvent.wheelDelta;
            if(isNaN(delta)) {
                delta = origiEvent.deltaY;
            }
            var scrollUp = delta < 0;
            if((scrollUp && scrollTop <= 0) || (!scrollUp && scrollTop >= scrollMax)) {
                mousewheelPrevent(event);
            } else if(isMsIE) {
                // Fix Internet Explorer and emulate natural scrolling
                var animOpt = { duration:200, easing:'linear' };
                if(scrollUp && -delta > scrollTop) {
                    $this.stop(true).animate({ scrollTop:0 }, animOpt);
                    mousewheelPrevent(event);
                } else if(!scrollUp && delta > scrollMax - scrollTop) {
                    $this.stop(true).animate({ scrollTop:scrollMax }, animOpt);
                    mousewheelPrevent(event);
                }
            }
        });
    });
};

Https://github.com/basselin/jquery-mousewheel-stop-propagation/blob/master/mousewheelStopPropagation.js

 0
Author: B.Asselin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-02 10:48:41

Najlepszym rozwiązaniem, jakie mogłem znaleźć, było wsłuchanie się w Zdarzenie scroll w oknie i ustawienie scrollTop na poprzedni scrollTop, jeśli div dziecka był widoczny.

prevScrollPos = 0
$(window).scroll (ev) ->
    if $('#mydiv').is(':visible')
        document.body.scrollTop = prevScrollPos
    else
        prevScrollPos = document.body.scrollTop

Jest migotanie w tle div dziecka, jeśli odpalisz wiele zdarzeń przewijania, więc to może być poprawione, ale to nie jest zauważone i to było wystarczające dla mojego przypadku użycia.

 0
Author: GijsjanB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-08 09:32:37

Nie używaj overflow: hidden; na body. Automatycznie przewija wszystko do góry. JavaScript też nie jest potrzebny. overflow: auto;:

Struktura HTML

<div class="overlay">
    <div class="overlay-content"></div>
</div>

<div class="background-content">
    lengthy content here
</div>

Stylizacja

.overlay{
    position: fixed;
    top: 0px;
    left: 0px;
    right: 0px;
    bottom: 0px;
    background-color: rgba(0, 0, 0, 0.8);

    .overlay-content {
        height: 100%;
        overflow: scroll;
    }
}

.background-content{
    height: 100%;
    overflow: auto;
}

Zagraj z demo tutaj .

 0
Author: Lucia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 11:11:07

Istnieje również zabawna sztuczka, aby zablokować rodzica scrollTop, gdy kursor myszy nad przewijanym elementem. W ten sposób nie musisz wdrażać własnego przewijania kół.

Oto przykład zapobiegania przewijaniu dokumentu, ale można go dostosować do dowolnego elementu.

scrollable.mouseenter(function ()
{
  var scroll = $(document).scrollTop();
  $(document).on('scroll.trap', function ()
  {
    if ($(document).scrollTop() != scroll) $(document).scrollTop(scroll);
  });
});

scrollable.mouseleave(function ()
{
  $(document).off('scroll.trap');
});
 0
Author: Sebastian Nowak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-15 16:34:15

M. K. zaoferował świetną wtyczkę w swojej odpowiedzi. Wtyczkę można znaleźć proszę.. Jednak, ze względu na zakończenie, pomyślałem, że byłoby dobrym pomysłem, aby umieścić go w jednej odpowiedzi na AngularJS.

  1. Zacznij od wstrzyknięcia bowera lub npm (w zależności od tego, co jest preferowane)

    bower install jquery-scrollLock --save
    npm install jquery-scroll-lock --save
    
  2. Dodać następującą dyrektywę. Wybieram dodanie go jako atrybutu

    (function() {
       'use strict';
    
        angular
           .module('app')
           .directive('isolateScrolling', isolateScrolling);
    
           function isolateScrolling() {
               return {
                   restrict: 'A',
                   link: function(sc, elem, attrs) {
                      $('.scroll-container').scrollLock();
                   }
               }
           }
    })();
    
  3. I ważny element, którego wtyczka nie dokumentuje w ich stronie internetowej jest struktura HTML, że musi podążać.

    <div class="scroll-container locked">
        <div class="scrollable" isolate-scrolling>
             ... whatever ...
        </div>
    </div>
    

Atrybut isolate-scrolling musi zawierać klasę scrollable i wszystko musi znajdować się wewnątrz klasy scroll-container lub dowolnej klasy, którą wybierzesz, A klasa locked musi być kaskadowa.

 0
Author: LOTUSMS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:13

Warto wspomnieć, że w nowoczesnych frameworkach, takich jak reactJS, AngularJS, VueJS, itp., Istnieją łatwe rozwiązania tego problemu, gdy mamy do czynienia z elementami o stałej pozycji. Przykładami są panele boczne lub elementy nakładane.

Technika ta nazywa się "portalem", co oznacza, że jeden z komponentów używanych w aplikacji, bez konieczności wyciągania go z miejsca, w którym go używasz, zamontuje swoje dzieci na dole elementu ciała, poza rodzicem, który próbujesz unikaj przewijania.

Zauważ, że nie uniknie przewijania samego elementu ciała. Możesz połączyć tę technikę i zamontować aplikację w przewijanym div, aby osiągnąć oczekiwany wynik.

Przykładowa implementacja portalu w material-ui Reacta: https://material-ui-next.com/api/portal/

 0
Author: Pandaiolo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-14 10:14:53

Jest es 6 crossbrowser + mobile vanila JS:

function stopParentScroll(selector) {
    let last_touch;
    let MouseWheelHandler = (e, selector) => {
        let delta;
        if(e.deltaY)
            delta = e.deltaY;
        else if(e.wheelDelta)
            delta = e.wheelDelta;
        else if(e.changedTouches){
            if(!last_touch){
                last_touch = e.changedTouches[0].clientY;
            }
            else{
                if(e.changedTouches[0].clientY > last_touch){
                    delta = -1;
                }
                else{
                    delta = 1;
                }
            }
        }
        let prevent = function() {
            e.stopPropagation();
            e.preventDefault();
            e.returnValue = false;
            return false;
        };

        if(selector.scrollTop === 0 && delta < 0){
            return prevent();
        }
        else if(selector.scrollTop === (selector.scrollHeight - selector.clientHeight) && delta > 0){
            return prevent();
        }
    };

    selector.onwheel = e => {MouseWheelHandler(e, selector)}; 
    selector.onmousewheel = e => {MouseWheelHandler(e, selector)}; 
    selector.ontouchmove  = e => {MouseWheelHandler(e, selector)};
}
 0
Author: Kaifat Kirsan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-14 02:00:51

Szukałem tego dla MooTools i to był pierwszy, który pojawił się. Oryginalny przykład MooTools będzie działał z przewijaniem w górę,ale nie przewijaniem w dół, więc postanowiłem napisać ten.


var stopScroll = function (e) {
    var scrollTo = null;
    if (e.event.type === 'mousewheel') {
        scrollTo = (e.event.wheelDelta * -1);
    } else if (e.event.type === 'DOMMouseScroll') {
        scrollTo = 40 * e.event.detail;
    }
    if (scrollTo) {
        e.preventDefault();
        this.scrollTo(0, scrollTo + this.scrollTop);
    }
    return false;
};

Użycie:

(function)($){
    window.addEvent('domready', function(){
        $$('.scrollable').addEvents({
             'mousewheel': stopScroll,
             'DOMMouseScroll': stopScroll
        });
    });
})(document.id);
 0
Author: Will B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-06 15:35:13

Proste rozwiązanie z eventem mouseweel:

$('.element').bind('mousewheel', function(e, d) {
    console.log(this.scrollTop,this.scrollHeight,this.offsetHeight,d);
    if((this.scrollTop === (this.scrollHeight - this.offsetHeight) && d < 0)
        || (this.scrollTop === 0 && d > 0)) {
        e.preventDefault();
    }
});
 -1
Author: egor.xyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-05 14:04:02

Możesz spróbować w ten sposób:

$('#element').on('shown', function(){ 
   $('body').css('overflow-y', 'hidden');
   $('body').css('margin-left', '-17px');
});

$('#element').on('hide', function(){ 
   $('body').css('overflow-y', 'scroll');
   $('body').css('margin-left', '0px');
});
 -2
Author: Korplex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-11 07:55:07