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 내부에 있을 때) 자바스크립트로 DIV를 수동으로 스크롤하는 것입니다(설정)..scrollTop
재산). 페이지하기 위해 하는 것이 의 더 나은 입니다.페이지 스크롤을 방지하기 위해 브라우저의 스크롤만 선택적으로 비활성화하고 DIV 스크롤은 비활성화하는 것이 대안이자 IMO의 더 나은 접근 방법입니다.아래에서 이 해결책을 보여주는 루디의 답변을 확인해보세요.
여기 있습니다.
$( '.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는 사용자 지정 이벤트 개체에 더 이상 노출되지 않으며 대신 네이티브 이벤트 개체에서 해당 개체를 검색해야 합니다.
이전 IE 버전과의 호환성(< 8)을 신경 쓰지 않는 경우 사용자 지정 jQuery 플러그인을 만든 다음 오버플로 요소에서 호출할 수 있습니다.
이 솔루션은 스크롤 동작을 덮어쓰지 않고 적절한 경우에만 차단하기 때문에 시메 비다스가 제안한 솔루션보다 장점이 있습니다.
$.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();
속성 CSS overscroll-behavior: contain;
요소에게.
마우스 스크롤 이벤트는 가끔 취소 가능할 것 같습니다. 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'
는 아래로 스크롤하는 것을 로는을다기면다기을ea는는gn . - 위치
scrollTop
위에,에.scrollHeight - scrollTop - offsetHeight
밑천으로
당신이
- 하고 ,
top = 0
, 아니면 - 아래로 스크롤하기, 그리고
bottom = 0
,
: 를 합니다 합니다.e.preventDefault()
(그리고 어쩌면 심지어는e.stopPropagation()
).
브라우저의 스크롤 동작을 무시하지 않는 것이 좋다고 생각합니다.해당되는 경우에만 취소하십시오.
완벽한 엑스브라우저는 아닐 수도 있지만, 그렇게 어렵지는 않습니다.맥의 듀얼 스크롤 방향은 까다롭겠지만...
이것이 도움이 되는지 확인해 보십시오.
데모: 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;
});
}
});
내 생각에 덜 까다로운 해결책은 스크롤 가능한 디브 위에 마우스를 올릴 때 몸에 숨겨진 오버플로를 설정하는 것입니다.이렇게 하면 신체가 스크롤 되는 것을 방지할 수 있지만 원하지 않는 "점프" 효과가 발생합니다.이와 관련하여 다음과 같은 솔루션이 적용됩니다.
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.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();
});
라이브 데모: http://jsfiddle.net/ibcaliax/bwmzfmq7/4/
여기 제가 응용 프로그램에서 사용한 솔루션이 있습니다.
본체 오버플로를 비활성화하고 전체 웹사이트 html을 컨테이너 div 안에 넣었습니다.웹 사이트 컨테이너에 오버플로가 발생하여 페이지를 예상대로 스크롤할 수 있습니다.
그런 다음 웹 사이트 전체를 포괄하는 z 지수가 더 높은 형제 디브(#Prevent)를 만들었습니다.#Prevent는 z-index가 더 높기 때문에 웹사이트 컨테이너와 겹칩니다.#Prevent(예방)가 표시되면 마우스가 더 이상 웹 사이트 컨테이너를 맴돌고 있지 않으므로 스크롤이 불가능합니다.
물론 마크업에서 #Prevent in Markup보다 z 지수가 높은 modal과 같은 다른 div를 배치할 수도 있습니다.이렇게 하면 스크롤 문제가 발생하지 않는 팝업 창을 만들 수 있습니다.
이 솔루션은 스크롤 막대(점프 효과)를 숨기지 않으므로 더 좋습니다.이벤트 청취자가 필요 없고 구현이 쉽습니다.IE7 및 8의 경우(특정 코드에 따라 다름) 플레이해야 하지만 모든 브라우저에서 작동합니다.
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;
}
}
스크롤을 비활성화/활성화
PreventScroll('on'); // prevent scrolling
PreventScroll('off'); // allow scrolling
스크롤 바가 있을 수 있는 여러 요소에 이 이벤트를 추가해야 했습니다.스크롤 바가 없는 경우에는 메인 스크롤 바가 제대로 작동하지 않았습니다.그래서 저는 @Shime 코드를 다음과 같이 약간 변경했습니다.
$( '.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();
}
});
이제 스크롤 바가 있는 요소만 있으면 기본 스크롤이 중지되지 않습니다.
순수 자바스크립트 버전의 비다스의 답변,el$
스크롤하는 평면의 DOM 노드입니다.
function onlyScrollElement(event, el$) {
var delta = event.wheelDelta || -event.detail;
el$.scrollTop += (delta < 0 ? 1 : -1) * 10;
event.preventDefault();
}
짝수를 여러번 붙이지 않도록 하세요!여기 예가 있습니다.
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);
주의할 점은, 함수를 첨부하기 전에 매번 함수를 재초기화할 경우, 함수가 일정해야 한다는 것입니다.var func = function (...)
그removeEventListener
작동하지 않습니다.
이것은 자바스크립트 없이도 할 수 있습니다.두 div의 스타일을 다음과 같이 설정할 수 있습니다.position: fixed
그리고.overflow-y: auto
. 둘 중 하나를 다른 하나보다 높게 설정해야 할 수도 있습니다.z-index
(겹칠 경우).
코드펜에 대한 기본적인 예는 다음과 같습니다.
특정 디브를 스크롤하는 동안 부모 스크롤을 방지하는 데 유용하고 다양한 옵션이 있는 플러그인입니다.
여기서 확인해보세요.
https://github.com/MohammadYounes/jquery-scrollLock
사용.
자바스크립트를 통한 스크롤 잠금 트리거:
$('#target').scrollLock();
마크업을 통해 스크롤 잠금 트리거:
<!-- 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>
데모 보기
필요한 건
e.preventDefault();
아동적 요소로
언급URL : https://stackoverflow.com/questions/7600454/how-to-prevent-page-scrolling-when-scrolling-a-div-element
'programing' 카테고리의 다른 글
자동 추가 기능 대 COM 추가 기능 (0) | 2023.09.18 |
---|---|
data.frame에서 조건부 값 대체 (0) | 2023.09.18 |
C function 포인터를 void 포인터로 캐스팅 (0) | 2023.09.18 |
C 또는 C++ 구조에 대한 특정 엔디안을 강제할 방법이 있습니까? (0) | 2023.09.18 |
데이터베이스에서 검색한 정보를 양식 안에 삽입할 수 없습니다. (0) | 2023.09.18 |