Mam element DIV z paskiem przewijania. Kiedy dojdzie do końca, moja strona zaczyna się przewijać. Czy w ogóle mogę powstrzymać to zachowanie?
Mam element DIV z paskiem przewijania. Kiedy dojdzie do końca, moja strona zaczyna się przewijać. Czy w ogóle mogę powstrzymać to zachowanie?
Odpowiedzi:
Możesz wyłączyć przewijanie całej strony, wykonując coś takiego:
<div onmouseover="document.body.style.overflow='hidden';" onmouseout="document.body.style.overflow='auto';"></div>
Znalazłem rozwiązanie.
To jest to, czego potrzebowałem.
A to jest kod.
http://jsbin.com/itajok/edit#javascript,html
Używa wtyczki jQuery.
Aktualizacja z powodu powiadomienia o wycofaniu
Stare zachowanie polegające na dodawaniu trzech argumentów (
delta,deltaXideltaY) do programu obsługi zdarzeń jest obecnie przestarzałe i zostanie usunięte w późniejszych wersjach.
Następnie event.deltaYnależ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;
});
Wybrane rozwiązanie to dzieło sztuki. Pomyślałem, że zasługuje na wtyczkę ...
$.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 z innymi hackami, które widziałem. Ciekawe, jak więcej o tym, jak to działa i jak szeroko byłoby to wspierane, ale wiwatuje Jeevanowi i temu, kto to wymyślił. BTW - edytor odpowiedzi stackoverflow tego potrzebuje!
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);
}
})
;
};
Świetnie sprawdza się w chrome i dużo prostszy niż inne rozwiązania ... daj mi znać, jak gdzie indziej wypada ...
wheelwydarzenie
Możesz użyć zdarzenia mouseover na div, aby wyłączyć pasek przewijania treści, a następnie zdarzenia mouseout, aby go ponownie aktywować?
Np. HTML
<div onmouseover="disableBodyScroll();" onmouseout="enableBodyScroll();">
content
</div>
A potem javascript w ten sposób:
var body = document.getElementsByTagName('body')[0];
function disableBodyScroll() {
body.style.overflowY = 'hidden';
}
function enableBodyScroll() {
body.style.overflowY = 'auto';
}
document.bodyzamiast tego.
Oto sposób na zrobienie tego na osi Y w różnych przeglądarkach, działa na komputerach stacjonarnych i urządzeniach mobilnych. Przetestowano na OSX 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();
}
}, {passive:false});
scrollArea.addEventListener("touchstart", function(event) {
this.previousClientY = event.touches[0].clientY;
}, {passive:false});
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;
}, {passive:false});
scrollTop === maxScroll przez scrollTop >= maxScroll. Wydaje się to dziwne w 1 przypadku, było potrzebne
Napisałem rozwiązanie tego 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);
e.currentTarget.
falsenie trzeba go określać, addEventListenerponieważ jest to ustawienie domyślne. Ponadto porównania powinny być prostymi nierównościami ( >i <), a nie >=lub <=.
Jak tu udzielono odpowiedzi , większość nowoczesnych przeglądarek obsługuje teraz overscroll-behavior: none;właściwość CSS, która zapobiega tworzeniu łańcuchów przewijania. I to wszystko, tylko jedna linijka!
overscroll-behavior: contain;.
Jeśli dobrze rozumiem twoje pytanie, chcesz zapobiec przewijaniu głównej treści, gdy wskaźnik myszy znajduje się nad elementem div (powiedzmy, pasek boczny). W tym celu pasek boczny może nie być elementem podrzędnym kontenera przewijania głównej zawartości (którym było okno przeglądarki), aby zapobiec pojawieniu się zdarzenia przewijania do jego elementu nadrzędnego.
Może to wymagać pewnych zmian w znacznikach w następujący sposób:
<div id="wrapper">
<div id="content">
</div>
</div>
<div id="sidebar">
</div>
Zobacz, jak działa na tych przykładowych skrzypcach i porównaj to z tymi przykładowymi skrzypcami które ma nieco inne zachowanie paska bocznego przy opuszczaniu myszy.
Zobacz także przewijanie tylko jednego określonego elementu div za pomocą głównego paska przewijania przeglądarki .
wyłącza to przewijanie w oknie, jeśli wejdziesz do elementu selektora. działa jak urok.
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");
});
Możesz wyłączyć 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>
$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();
}
});
W oparciu o odpowiedź Ceeda, oto wersja, która pozwala na zagnieżdżanie chronionych elementów przewijania. Tylko element, nad którym znajduje się mysz, będzie się przewijał i przewija się całkiem płynnie. Ta wersja jest również ponownie wprowadzana. Może być używany wiele razy na tym samym elemencie i poprawnie usunie i ponownie zainstaluje uchwyty.
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 prostym sposobem użycia jest dodanie klasy, na przykład scroll-guard, do wszystkich elementów na stronie, na których możesz przewijać. Następnie użyj, $('.scroll-guard').scrollGuard()aby ich chronić.
Jeśli zastosujesz overflow: hiddenstyl, powinien zniknąć
edycja: właściwie źle odczytałem twoje pytanie, to tylko ukryje pasek przewijania, ale nie sądzę, że tego szukasz.
Nie mogłem uzyskać żadnej odpowiedzi do pracy w Chrome i Firefox, więc wymyśliłem to połączenie:
$someElement.on('mousewheel DOMMouseScroll', scrollProtection);
function scrollProtection(event) {
var $this = $(this);
event = event.originalEvent;
var direction = (event.wheelDelta * -1) || (event.detail);
if (direction < 0) {
if ($this.scrollTop() <= 0) {
return false;
}
} else {
if ($this.scrollTop() + $this.innerHeight() >= $this[0].scrollHeight) {
return false;
}
}
}