Programing

DIV 요소를 스크롤 할 때 페이지 스크롤을 방지하는 방법은 무엇입니까?

lottogame 2020. 9. 4. 08:02
반응형

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의 이중 스크롤 방향이 까다로울 수도 있습니다.


이것이 도움이되는지 확인하십시오.

데모 : 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;
};

여기에 브라우저 네이티브 스크롤을 파괴하지 않는 jQuery가없는 간단한 솔루션이 있습니다 (이는 인위적 / 추악한 스크롤 없음).

var scrollable = document.querySelector('.scrollable');

scrollable.addEventListener('wheel', function(event) {
    var deltaY = event.deltaY;
    var contentHeight = scrollable.scrollHeight;
    var visibleHeight = scrollable.offsetHeight;
    var scrollTop = scrollable.scrollTop;

    if (scrollTop === 0 && deltaY < 0)
        event.preventDefault();
    else if (visibleHeight + scrollTop === contentHeight && deltaY > 0)
        event.preventDefault();
});

Live demo: http://jsfiddle.net/ibcaliax/bwmzfmq7/4/


Here is my solution I've used in applications.

I disabled the body overflow and placed the entire website html inside container div's. The website containers have overflow and therefore the user may scroll the page as expected.

I then created a sibling div (#Prevent) with a higher z-index that covers the entire website. Since #Prevent has a higher z-index, it overlaps the website container. When #Prevent is visible the mouse is no longer hovering the website containers, so scrolling isn't possible.

You may of course place another div, such as your modal, with a higher z-index than #Prevent in the markup. This allows you to create pop-up windows that don't suffer from scrolling issues.

This solution is better because it doesn't hide the scrollbars (jumping affect). It doesn't require event listeners and it's easy to implement. It works in all browsers, although with IE7 & 8 you have to play around (depends on your specific code).

html

<body>
  <div id="YourModal" style="display:none;"></div>
  <div id="Prevent" style="display:none;"></div>
  <div id="WebsiteContainer">
     <div id="Website">
     website goes here...
     </div>
  </div>
</body>

css

body { overflow: hidden; }

#YourModal {
 z-index:200;
 /* modal styles here */
}

#Prevent {
 z-index:100;
 position:absolute;
 left:0px;
 height:100%;
 width:100%;
 background:transparent;
}

#WebsiteContainer {
  z-index:50;
  overflow:auto;
  position: absolute;
  height:100%;
  width:100%;
}
#Website {
  position:relative;
}

jquery/js

function PreventScroll(A) { 
  switch (A) {
    case 'on': $('#Prevent').show(); break;
    case 'off': $('#Prevent').hide(); break;
  }
}

disable/enable the scroll

PreventScroll('on'); // prevent scrolling
PreventScroll('off'); // allow scrolling

I needed to add this event to multiple elements that might have a scrollbar. For the cases where no scrollbar was present, the main scrollbar didn't work as it should. So i made a small change to @Šime code as follows:

$( '.scrollable' ).on( 'mousewheel DOMMouseScroll', function ( e ) {
    if($(this).prop('scrollHeight') > $(this).height())
    {
        var e0 = e.originalEvent, delta = e0.wheelDelta || -e0.detail;

        this.scrollTop += ( delta < 0 ? 1 : -1 ) * 30;
        e.preventDefault();
    }       
});

Now, only elements with a scrollbar will prevent the main scroll from begin stopped.


Pure javascript version of Vidas's answer, el$ is the DOM node of the plane you are scrolling.

function onlyScrollElement(event, el$) {
    var delta = event.wheelDelta || -event.detail;
    el$.scrollTop += (delta < 0 ? 1 : -1) * 10;
    event.preventDefault();
}

Make sure you dont attach the even multiple times! Here is an example,

var ul$ = document.getElementById('yo-list');
// IE9, Chrome, Safari, Opera
ul$.removeEventListener('mousewheel', onlyScrollElement);
ul$.addEventListener('mousewheel', onlyScrollElement);
// Firefox
ul$.removeEventListener('DOMMouseScroll', onlyScrollElement);
ul$.addEventListener('DOMMouseScroll', onlyScrollElement);

Word of caution, the function there needs to be a constant, if you reinitialize the function each time before attaching it, ie. var func = function (...) the removeEventListener will not work.


You can do this without JavaScript. You can set the style on both divs to position: fixed and overflow-y: auto. You may need to make one of them higher than the other by setting its z-index (if they overlap).

Here's a basic example on CodePen.


Here is the plugin that is useful for preventing parent scroll while scrolling a specific div and has a bunch of options to play with.

Check it out here:

https://github.com/MohammadYounes/jquery-scrollLock

Usage

Trigger Scroll Lock via JavaScript:

$('#target').scrollLock();

Trigger Scroll Lock via Markup:

    <!-- HTML -->
<div data-scrollLock
     data-strict='true'
     data-selector='.child'
     data-animation='{"top":"top locked","bottom":"bottom locked"}'
     data-keyboard='{"tabindex":0}'
     data-unblock='.inner'>
     ...
</div>

<!-- JavaScript -->
<script type="text/javascript">
  $('[data-scrollLock]').scrollLock()
</script>

View Demo


Use below CSS property overscroll-behavior: contain; to child element

참고URL : https://stackoverflow.com/questions/7600454/how-to-prevent-page-scrolling-when-scrolling-a-div-element

반응형