Pytanie Przewijanie elementu potomnego przewija okno, jak mogę to zatrzymać?


Mam div, z paskiem przewijania, Kiedy osiągnie koniec, moja strona zaczyna się przewijać. Czy mimo to mogę zatrzymać to zachowanie?


82
2018-04-18 14:11


pochodzenie


@NGLN nie jest duplikatem, innym pytaniem. - sidewinderguy
Możliwy duplikat Zapobieganie przewijaniu elementu nadrzędnego, gdy pozycja przewijania elementu wewnętrznego osiąga górę / dół? - TylerH


Odpowiedzi:


Możesz dezaktywować przewijanie całej strony, wykonując coś takiego:

<div onmouseover="document.body.style.overflow='hidden';" onmouseout="document.body.style.overflow='auto';"></div>

67
2018-04-18 14:21



Dobrze, ale sprawia, że ​​pasek przewijania przeglądarki znika po każdym najechaniu na element div. - cstack
@Cstack masz rację, dlatego własna odpowiedź OP (Jeevan) jest lepsza. - Imran Bughio
Wiele kółek do przewijania w przeglądarce znika i pojawia się ponownie na podstawie tego, jak użytkownik porusza myszą, więc powyższy komentarz nie stanowi już problemu. - Keith Holliday
To rozwiązanie nie działa, gdy strona jest osadzona w elemencie iframe. - Gautam Krishnan
nie jest rozwiązaniem. ustawienie przelewu na ukryty ukrywa pasek przewijania, który nagle zmienia format całej zawartości elementu zewnętrznego. również zakłada, że ​​zewnętrznym elementem jest ciało, ale może to być kolejny przewijany div. - robisrob


Znaleziono rozwiązanie.

http://jsbin.com/itajok

Tego właśnie potrzebowałem.

I to jest kod.

http://jsbin.com/itajok/edit#javascript,html

Używa wtyczki jQuery.


Zaktualizuj z powodu powiadomienia o wycofaniu

Od jquery-mousewheel:

Stare zachowanie dodawania trzech argumentów (delta, deltaX, i deltaY)   do obsługi zdarzenia jest teraz przestarzałe i zostanie usunięte później   wydania.

Następnie, event.deltaY należy teraz użyć:

var toolbox = $('#toolbox'),
    height = toolbox.height(),
    scrollHeight = toolbox.get(0).scrollHeight;

toolbox.off("mousewheel").on("mousewheel", function (event) {
  var blockScrolling = this.scrollTop === scrollHeight - height && event.deltaY < 0 || this.scrollTop === 0 && event.deltaY > 0;
  return !blockScrolling;
});

Próbny


41
2018-05-09 10:57



Twój link używa github dla js i breaks, ponieważ content-type blah blah tutaj działa: jsbin.com/itajok/207 - Michael J. Calkins
Obydwa jbiny nie działają w emulatorze urządzenia z Chrome i na iPhonie. Czy ktoś wie, czy to nadal działa? - Dirk Boer
Twoje "rozwiązanie" działa tylko w przypadku zdarzeń przewijania myszy, a nie w stronę w górę / w dół lub klawiszy strzałek. - Scott
Dlaczego wymagane jest "wyłączenie"? - Brad Johnson


Wybrane rozwiązanie jest dziełem sztuki. Myślałem, że było warte wtyczki ....

$.fn.scrollGuard = function() {
    return this
        .on( 'wheel', function ( e ) {
            var event = e.originalEvent;
            var d = event.wheelDelta || -event.detail;
            this.scrollTop += ( d < 0 ? 1 : -1 ) * 30;
            e.preventDefault();
        });
};    

Jest to dla mnie ciągła niedogodność, a to rozwiązanie jest tak czyste w porównaniu do innych hacków, jakie widziałem. Ciekawiło mnie, jak więcej o tym, jak to działa i jak szeroko jest obsługiwane, ale wiwatuje Jeevanowi i temu, kto oryginalnie to wymyślił. BTW - edytor edytora stackoverflow tego wymaga!

AKTUALIZACJA

Uważam, że jest to lepsze, ponieważ w ogóle nie próbuje manipulować DOM, a jedynie zapobiega warunkowemu bulgotaniu ...

$.fn.scrollGuard2 = function() {
  return this
    .on( 'wheel', function ( e ) {
      var $this = $(this);
      if (e.originalEvent.deltaY < 0) {
        /* scrolling up */
        return ($this.scrollTop() > 0);
      } else {
        /* scrolling down */
        return ($this.scrollTop() + $this.innerHeight() < $this[0].scrollHeight);
      }
    })
  ;
};    

Działa świetnie w chromie i znacznie prostsze niż inne rozwiązania ... daj mi znać, jak to się dzieje gdzie indziej ...

SKRZYPCE


15
2018-05-07 21:31



dodanie zdarzenia DOMMouseScroll sprawia, że ​​działa z przeglądarką Firefox → jsfiddle.net/chodorowicz/egqy7mbz/1 - chodorowicz
Jestem zaskoczony, że to nie jest napisane w jquery. Myślałem, że jednym z głównych punktów nie jest dbanie o przeglądarkę, której używasz. - robisrob
w rzeczywistości wygląda na to, że oba są przestarzałe ... wheel zdarzenie - robisrob
Powoduje to gwałtowne przewijanie w Chrome na moim MacBooku. Przyjęte rozwiązanie nie ma tego problemu. - danvk
niezadowalający. jest tak wiele różnych wersji tego. wydaje się ważnym aspektem interfejsu użytkownika i naprawdę zaskakuje, że jest to zachowanie domyślne, gdy jest tak niezrozumiałe. Oczywiście przeglądarka jest wyposażona, aby wiedzieć, że wewnętrzny przewijany div jest na swoim limicie, aby móc zastosować zdarzenie do okna, więc dlaczego nie ma dostępnych uchwytów do zapytania? - robisrob


Możesz użyć zdarzenia mouseover na div, aby wyłączyć pasek przewijania ciała, a następnie wydarzenie mouseout, aby je ponownie aktywować?

Na przykład. HTML

<div onmouseover="disableBodyScroll();" onmouseout="enableBodyScroll();">
    content
</div>

A potem javascript wygląda tak:

var body = document.getElementsByTagName('body')[0];
function disableBodyScroll() {
    body.style.overflowY = 'hidden';
}
function enableBodyScroll() {
    body.style.overflowY = 'auto';
}

8
2018-04-18 14:22



Możesz użyć document.body w zamian też. - Ry-♦


Jeśli poprawnie zrozumiem twoje pytanie, nie chcesz przewijać głównej zawartości, gdy mysz znajduje się nad działem div (powiedzmy bocznym). W tym celu pasek boczny nie może być dzieckiem przewijanego kontenera głównej zawartości (która była oknem przeglądarki), aby zapobiec przepełnieniu zdarzenia przewijania do jego obiektu nadrzędnego.

Może to wymagać zmian w znacznikach w następujący sposób:

<div id="wrapper"> 
    <div id="content"> 
    </div> 
</div> 
<div id="sidebar"> 
</div> 

Zobacz, jak to działa to przykładowe skrzypce i porównaj to z to przykładowe skrzypce który ma nieco inne zachowanie myszy na pasku bocznym.

Zobacz też przewiń tylko jeden konkretny div z głównym paskiem przewijania przeglądarki.


7
2018-04-18 14:52



W tym przypadku pasek boczny znajduje się poza opakowaniem div. Więc nie sądzę, że zwój będzie bańką dla rodzica - Jeevan
Przez "tę sprawę" masz na myśli twoją sprawę? Jeśli nie: masz dokładnie rację. Jeśli tak, to: jeśli twoja strona przewija się po przewinięciu div, to wiadomość przewija się do rodzica div, więc myślę, że twoja strona i div nie są rodzeństwem, ale rodzicem i dzieckiem. - NGLN
Tak, strona jest rodzicem mojego div, więc po dotarciu do końca zaczyna przewijać stronę, której nie chcę. - Jeevan
Jeśli nie możesz sprawić, by twój div był rodzeństwem głównej treści, to problemu nie można naprawić samodzielnie za pomocą HTML + CSS. Jest to domyślne zachowanie. - NGLN
Myślę, że jest to najbardziej skuteczne rozwiązanie wszystkich udzielonych odpowiedzi; z dobrym czystym znacznikiem u podstawy strony, w celu uzyskania pożądanego zachowania wymagane są znacznie mniejsze ataki CSS i JS. - ZaLiTHkA


Napisałem rozwiązanie problemu

  var div;
  div = document.getElementsByClassName('selector')[0];

  div.addEventListener('mousewheel', function(e) {
    if (div.clientHeight + div.scrollTop + e.deltaY >= div.scrollHeight) {
      e.preventDefault();
      div.scrollTop = div.scrollHeight;
    } else if (div.scrollTop + e.deltaY <= 0) {
      e.preventDefault();
      div.scrollTop = 0;
    }
  }, false);

7
2018-06-30 08:58



Jedno z niewielu rozwiązań, które działa bez elementów strony irytująco skaczących z powodu ustawionego ukrytego przelewu. - Reinout van Kempen
+1 to solidne rozwiązanie. jeśli podłączysz to do przewijanego kontenera, będziesz chciał div w tym przykładzie e.currentTarget. - Matt
bardzo czyste rozwiązanie. Dzięki - Thinh Bui
Pracował w Chrome 61.0.3163.100 i Safari 11.0, ale nie w FireFox 56.0 (Mac OS El Capitan) - BigJ
To najlepsze rozwiązanie natywne. Jednak, false nie trzeba określać addEventListener ponieważ to jest domyślne. Ponadto porównania powinny być prostymi nierównościami (> i <), nie >= lub <=. - Quolonel Questions


Oto sposób na różne przeglądarki, aby to zrobić na osi Y, działa na komputerach i urządzeniach mobilnych. Testowany na OS X i iOS.

var scrollArea = this.querySelector(".scroll-area");
scrollArea.addEventListener("wheel", function() {
    var scrollTop = this.scrollTop;
    var maxScroll = this.scrollHeight - this.offsetHeight;
    var deltaY = event.deltaY;
    if ( (scrollTop === maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
        event.preventDefault();
    }
});

scrollArea.addEventListener("touchstart", function(event) {
    this.previousClientY = event.touches[0].clientY;
});

scrollArea.addEventListener("touchmove", function(event) {
    var scrollTop = this.scrollTop;
    var maxScroll = this.scrollHeight - this.offsetHeight;
    var currentClientY = event.touches[0].clientY;
    var deltaY = this.previousClientY - currentClientY;
    if ( (scrollTop === maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
        event.preventDefault();
    }
    this.previousClientY = currentClientY;
});

4
2017-07-02 22:23



Działa to świetnie! Wow, dokładnie to, co szukałem. Wymaga zdecydowanie więcej awansów. - delato468
To rozwiązanie działa całkiem dobrze, ale wymaga niewielkiej korekty: trzeba zmienić scrollTop === maxScroll  przez scrollTop >= maxScroll. Wydaje się dziwne w 1 przypadku, było to potrzebne - tchiot.ludo


Możesz dezaktywować przewijanie całej strony, wykonując coś takiego, ale wyświetlając pasek przewijania!

<div onmouseover="document.body.style.overflow='hidden'; document.body.style.position='fixed';" onmouseout="document.body.style.overflow='auto'; document.body.style.position='relative';"></div>

2
2018-06-17 16:27



działa idealnie @joseantgv - Ewall Tester


$this.find('.scrollingDiv').on('mousewheel DOMMouseScroll', function (e) {
  var delta = -e.originalEvent.wheelDelta || e.originalEvent.detail;
  var scrollTop = this.scrollTop;
  if((delta < 0 && scrollTop === 0) || (delta > 0 && this.scrollHeight - this.clientHeight - scrollTop === 0)) {
    e.preventDefault();
  }
});

2
2017-11-02 19:43





to wyłącza przewijanie w oknie, jeśli wpiszesz element selektora. działa jak amulety.

elements = $(".selector");

elements.on('mouseenter', function() {
    window.currentScrollTop = $(window).scrollTop();
    window.currentScrollLeft = $(window).scrollTop();
    $(window).on("scroll.prevent", function() {
        $(window).scrollTop(window.currentScrollTop);
        $(window).scrollLeft(window.currentScrollLeft);
    });
});

elements.on('mouseleave', function() {
    $(window).off("scroll.prevent");
});

2
2017-09-03 12:49





W oparciu o odpowiedź ceed, tutaj jest wersja, która pozwala zagnieżdżać elementy chronione przed przewijaniem. Zostanie przewinięty tylko element myszy, który przewija się całkiem płynnie. Ta wersja również jest ponownie wprowadzana. Może być używany wielokrotnie na tym samym elemencie i poprawnie usunie i ponownie zainstaluje procedury obsługi.

jQuery.fn.scrollGuard = function() {
    this
        .addClass('scroll-guarding')
        .off('.scrollGuard').on('mouseenter.scrollGuard', function() {
            var $g = $(this).parent().closest('.scroll-guarding');
            $g = $g.length ? $g : $(window);
            $g[0].myCst = $g.scrollTop();
            $g[0].myCsl = $g.scrollLeft();
            $g.off("scroll.prevent").on("scroll.prevent", function() {
                $g.scrollTop($g[0].myCst);
                $g.scrollLeft($g[0].myCsl);
            });
        })
        .on('mouseleave.scrollGuard', function() {
            var $g = $(this).parent().closest('.scroll-guarding');
            $g = $g.length ? $g : $(window);
            $g.off("scroll.prevent");
        });
};

Jednym z łatwych sposobów użycia jest dodanie klasy, takiej jak scroll-guard, do wszystkich elementów strony, które można przewijać. Następnie użyj $('.scroll-guard').scrollGuard() aby ich strzec.


1
2017-10-12 21:09