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