[jquery] DIV 요소를 스크롤 할 때 페이지 스크롤을 방지하는 방법은 무엇입니까?
div 내부에서 스크롤하는 신체 기능을 방지하기 위해 다양한 기능을 검토하고 테스트했으며 작동해야하는 기능을 결합했습니다.
$('.scrollable').mouseenter(function() {
$('body').bind('mousewheel DOMMouseScroll', function() {
return false;
});
$(this).bind('mousewheel DOMMouseScroll', function() {
return true;
});
});
$('.scrollable').mouseleave(function() {
$('body').bind('mousewheel DOMMouseScroll', function() {
return true;
});
});
- 컨테이너 내에서 스크롤이 가능하기를 원하는 모든 스크롤을 중지합니다.
- 마우스를 놓아도 비활성화되지 않습니다.
어떤 아이디어 나 더 나은 방법이 있습니까?
답변
업데이트 2 : 내 솔루션은 브라우저의 기본 스크롤을 모두 비활성화 한 다음 (커서가 DIV 내부에있을 때) JavaScript로 DIV를 수동으로 스크롤 ( .scrollTop
속성 을 설정하여 )하는 것입니다. 대안 및 IMO 더 나은 접근 방식은 DIV 스크롤이 아닌 페이지 스크롤을 방지하기 위해 브라우저의 스크롤을 선택적으로 비활성화하는 것입니다. 이 솔루션을 보여주는 Rudie의 답변을 아래에서 확인하십시오.
여기 있습니다 :
$( '.scrollable' ).on( 'mousewheel DOMMouseScroll', function ( e ) {
var e0 = e.originalEvent,
delta = e0.wheelDelta || -e0.detail;
this.scrollTop += ( delta < 0 ? 1 : -1 ) * 30;
e.preventDefault();
});
라이브 데모 : https://jsbin.com/howojuq/edit?js,output
따라서 수동으로 스크롤 위치를 설정 한 다음 기본 동작 (DIV 또는 전체 웹 페이지 스크롤)을 방지합니다.
업데이트 1 : Chris가 아래 주석에서 언급했듯이 최신 버전의 jQuery에서는 델타 정보가 .originalEvent
객체 내에 중첩됩니다. 즉, jQuery는 더 이상 사용자 정의 Event 객체에 정보를 노출하지 않으며 대신 기본 Event 객체에서 검색해야합니다. .
답변
이전 IE 버전 (<8)과의 호환성에 관심이 없다면 사용자 지정 jQuery 플러그인을 만든 다음 오버플로 요소에서 호출 할 수 있습니다.
이 솔루션은 Šime Vidas가 제안한 것보다 장점이 있습니다. 스크롤 동작을 덮어 쓰지 않고 적절할 때 차단하기 때문입니다.
$.fn.isolatedScroll = function() {
this.bind('mousewheel DOMMouseScroll', function (e) {
var delta = e.wheelDelta || (e.originalEvent && e.originalEvent.wheelDelta) || -e.detail,
bottomOverflow = this.scrollTop + $(this).outerHeight() - this.scrollHeight >= 0,
topOverflow = this.scrollTop <= 0;
if ((delta < 0 && bottomOverflow) || (delta > 0 && topOverflow)) {
e.preventDefault();
}
});
return this;
};
$('.scrollable').isolatedScroll();
답변
가끔 mousescroll 이벤트를 취소 할 수 있다고 생각합니다. http://jsfiddle.net/rudiedirkx/F8qSq/show/
$elem.on('wheel', function(e) {
var d = e.originalEvent.deltaY,
dir = d < 0 ? 'up' : 'down',
stop = (dir == 'up' && this.scrollTop == 0) ||
(dir == 'down' && this.scrollTop == this.scrollHeight-this.offsetHeight);
stop && e.preventDefault();
});
이벤트 핸들러 내에서 알아야 할 사항 :
-
d = e.originalEvent.deltaY, dir = d < 0 ? 'up' : 'down'
양수는 아래로 스크롤을 의미하므로 스크롤 방향 -
scrollTop
위쪽,scrollHeight - scrollTop - offsetHeight
아래쪽 스크롤 위치
당신이
- 위로 스크롤 및
top = 0
, 또는 - 아래로 스크롤 및
bottom = 0
,
이벤트 취소 : e.preventDefault()
(그리고 어쩌면 e.stopPropagation()
).
브라우저의 스크롤 동작을 무시하지 않는 것이 좋습니다. 해당되는 경우에만 취소하십시오.
완벽하게 xbrowser는 아니지만 매우 어렵지는 않습니다. Mac의 이중 스크롤 방향이 까다로울 수도 있습니다.
답변
overscroll-behavior: contain;
하위 요소에 CSS 속성 아래 사용
답변
이것이 도움이되는지 확인하십시오.
데모 : jsfiddle
$('#notscroll').bind('mousewheel', function() {
return false
});
편집하다:
이 시도:
$("body").delegate("div.scrollable","mouseover mouseout", function(e){
if(e.type === "mouseover"){
$('body').bind('mousewheel',function(){
return false;
});
}else if(e.type === "mouseout"){
$('body').bind('mousewheel',function(){
return true;
});
}
});
답변
덜 해키하지 않는 해결책은 스크롤 가능한 div 위로 마우스를 가져갈 때 본문에 오버플로를 숨기도록 설정하는 것입니다. 이렇게하면 본문이 스크롤되지 않지만 원하지 않는 “점프”효과가 발생합니다. 다음 솔루션이이를 해결합니다.
jQuery(".scrollable")
.mouseenter(function(e) {
// get body width now
var body_width = jQuery("body").width();
// set overflow hidden on body. this will prevent it scrolling
jQuery("body").css("overflow", "hidden");
// get new body width. no scrollbar now, so it will be bigger
var new_body_width = jQuery("body").width();
// set the difference between new width and old width as padding to prevent jumps
jQuery("body").css("padding-right", (new_body_width - body_width)+"px");
})
.mouseleave(function(e) {
jQuery("body").css({
overflow: "auto",
padding-right: "0px"
});
})
필요한 경우 코드를 더 똑똑하게 만들 수 있습니다. 예를 들어 본문에 이미 패딩이 있는지 테스트하고 예인 경우 새 패딩을 추가 할 수 있습니다.
답변
위의 솔루션에는 Firefox와 관련된 약간의 실수가 있습니다. Firefox에서 “DOMMouseScroll”이벤트에는 e.detail 속성이 없습니다.이 속성을 얻으려면 다음 ‘e.originalEvent.detail’을 작성해야합니다.
다음은 Firefox 용 작업 솔루션입니다.
$.fn.isolatedScroll = function() {
this.on('mousewheel DOMMouseScroll', function (e) {
var delta = e.wheelDelta || (e.originalEvent && e.originalEvent.wheelDelta) || -e.originalEvent.detail,
bottomOverflow = (this.scrollTop + $(this).outerHeight() - this.scrollHeight) >= 0,
topOverflow = this.scrollTop <= 0;
if ((delta < 0 && bottomOverflow) || (delta > 0 && topOverflow)) {
e.preventDefault();
}
});
return this;
};