DIV तत्व को स्क्रॉल करते समय पेज स्क्रॉलिंग को कैसे रोकें?


94

मैंने एक डिव के अंदर स्क्रॉल करने के लिए शरीर की क्षमता को रोकने के लिए विभिन्न कार्यों की समीक्षा और परीक्षण किया है और एक फ़ंक्शन को संयुक्त किया है जो काम करना चाहिए।

$('.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;
    });
});
  • यह सभी स्क्रॉलिंग को रोक रहा है जहां मैं चाहता हूं कि अभी भी कंटेनर के अंदर स्क्रॉल करना संभव हो
  • यह भी माउस छुट्टी पर निष्क्रिय नहीं है

किसी भी विचार, या ऐसा करने के बेहतर तरीके?


यू बॉडी को मूसवेल से असत्य के रूप में सेट करते हैं, शायद यह समस्या है, मुझे लगता है कि आपका कंटेनर शरीर के अंदर सही है
रिकार्डो बिन्स

@ric_bfa हाँ लेकिन इसे कैसे ठीक किया जाए
RIK

शरीर के बजाय, अपनी कक्षा / आईडी कंटेनर सेट करें
रिकार्डो बिन्स

शायद मुझे स्पष्ट करना चाहिए। जब माउस तत्व के अंदर होता है।। 'स्क्रॉल' शरीर की स्क्रॉल करने की क्षमता को निष्क्रिय किया जाना चाहिए
RIK

4
वहाँ सभी सीएसएस और कोई जावास्क्रिप्ट के साथ ऐसा करने का एक तरीका नहीं है?
छरवे

जवाबों:


165

अद्यतन 2: मेरा समाधान ब्राउज़र की देशी स्क्रॉलिंग को पूरी तरह से अक्षम करने पर आधारित है (जब कर्सर डीआईवी के अंदर होता है) और फिर मैन्युअल रूप से जावास्क्रिप्ट को अपनी .scrollTopसंपत्ति सेट करके स्क्रॉल करें । पेज स्क्रॉल को रोकने के लिए एक वैकल्पिक और IMO बेहतर तरीका केवल ब्राउज़र की स्क्रॉलिंग को चुनिंदा रूप से अक्षम करना होगा, लेकिन DIV स्क्रॉल को नहीं। नीचे रूडी के उत्तर की जाँच करें जो इस समाधान को प्रदर्शित करता है।


हेयर यू गो:

$( '.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: जैसा कि क्रिस ने नीचे दिए गए टिप्पणियों में उल्लेख किया है, jQuery के नए संस्करणों में, डेल्टा जानकारी को .originalEventऑब्जेक्ट के भीतर नेस्टेड किया जाता है, अर्थात jQuery अपने कस्टम इवेंट ऑब्जेक्ट में इसे उजागर नहीं करता है और हमें इसे मूल ईवेंट ऑब्जेक्ट से पुनर्प्राप्त करना होगा ।


2
@RobinKnight नहीं, ऐसा नहीं लगता है। यहाँ कार्यशील डेमो है: jsfiddle.net/XNwbt/1 और यहाँ उन रेखाओं के साथ डेमो हटा दिया गया है: jsfiddle.net/XNwbt/2
asime Vidas

1
आपकी मैनुअल स्क्रॉलिंग फ़ायरफ़ॉक्स 10 पर कम से कम लिनक्स और मैक पर है। अगर आप -e.detailफ़ायरफ़ॉक्स (मैक, लिनक्स), सफारी (मैक), और क्रोमियम (लिनक्स) में परीक्षण किया है , तो सही ढंग से काम करने लगता है ।
अनोमि

1
@Anomie यह सही है। मोज़िला का .detailचिह्न, .wheelData(जो कि क्रोम / IE है) के संकेत के अनुरूप नहीं है , इसलिए हमें इसे मैन्युअल रूप से उलटना होगा। मेरा उत्तर ठीक करने के लिए धन्यवाद।
07इमे विदेस

8
मैंने इसका इस्तेमाल किया, धन्यवाद! मुझे इस थो को जोड़ने की आवश्यकता थी:if( e.originalEvent ) e = e.originalEvent;
निकोसो

2
@ AfterimeVidas मैंने अपने सॉफ़्टवेयर में इसे लागू करने के बाद मैंने इसके लिए एक समायोजन किया। महत्वपूर्ण नहीं है, लेकिन संभवतः स्क्रॉल प्रॉपर्टी के लिए एक डिटेल चेक जोड़ें, ताकि जब कोई स्क्रॉल न हो तो गतिरोध स्क्रॉल को रोका जा सके। if ( $(this)[0].scrollHeight !== $(this).outerHeight() ) { //yourcode }स्क्रॉलबार होने पर ही निष्पादित होगा।
user0000001

30

यदि आप पुराने IE संस्करणों (<8) के साथ संगतता की परवाह नहीं करते हैं, तो आप एक कस्टम jQuery प्लगइन बना सकते हैं और फिर इसे अतिप्रवाह तत्व पर कॉल कर सकते हैं।

इस समाधान में प्रस्तावित has टाइम विद पर एक फायदा है, क्योंकि यह स्क्रॉलिंग व्यवहार को अधिलेखित नहीं करता है - यह उचित होने पर इसे ब्लॉक करता है।

$.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();

2
धन्यवाद! मुझे लगता है कि डिफ़ॉल्ट व्यवहार को अधिलेखित न करने के लिए इसका अधिक उपयुक्त है। क्रॉस-ब्राउज़र सपोर्ट के लिए इसे jQuery माउस व्हील प्लगइन का उपयोग किया जा सकता है ।
मीट्टीना

दुर्भाग्य से यह क्रोम 52 (OSX 10.10) में गड़बड़ है। हालांकि सफारी में पूरी तरह से काम करता है।
ठंढा

1
धन्यवाद! अन्य समाधानों ने स्क्रॉलिंग को धीमा और छोटी कर दिया
agrublev

@wojcikstefan, मुझे क्रोम में यह चेतावनी मिल रही है:[Violation] Added non-passive event listener to a scroll-blocking 'mousewheel' event. Consider marking event handler as 'passive' to make the page more responsive.
सैयद

21

मुझे लगता है कि कभी-कभी मॉस्कोक्रॉल इवेंट को रद्द करना संभव है: 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 नहीं है, लेकिन यह बहुत कठिन नहीं हो सकता है। शायद मैक की दोहरी स्क्रॉल दिशा हालांकि मुश्किल है ...


2
मैं उपकरणों (टैबलेट / फोन) के लिए समान कार्यक्षमता को कैसे लागू करूं, मुझे लगता है कि
टचमूव

6

नीचे सीएसएस संपत्ति overscroll-behavior: contain;का उपयोग बाल तत्व के लिए करें


इस देशी CSS नियम की तुलना में अन्य सभी समाधान ओवरकिल हैं। अच्छी तरह से किया।
TechWisdom

3

देखें कि क्या यह आपकी मदद करता है:

डेमो: 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;
           });
       }
    });

आपके तत्व अलग हैं, जबकि मेरा एक दूसरे में निहित है।
RIK

3

मेरी राय में एक कम हैकी समाधान, जब आप स्क्रॉल करने योग्य 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"
        });
    })

जरूरत पड़ने पर आप अपना कोड स्मार्ट बना सकते हैं। उदाहरण के लिए, यदि आप परीक्षण कर सकते हैं कि शरीर में पहले से ही एक गद्दी है और यदि हाँ, तो नए गद्दी को उसमें जोड़ें।


3

ऊपर दिए गए समाधान में फ़ायरफ़ॉक्स के बारे में थोड़ी गलती है। फ़ायरफ़ॉक्स में "DOMMouseScroll" ईवेंट में कोई भी e.detail प्रॉपर्टी नहीं है, इस प्रॉपर्टी को प्राप्त करने के लिए आपको निम्नलिखित 'e.originalEvent.detail' लिखना चाहिए।

यहाँ फ़ायरफ़ॉक्स के लिए एक काम कर समाधान है:

$.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;
};

यह बहुत अच्छी तरह से काम करता है सिवाय इसके कि जब आप ऊपर या नीचे से दुर्घटना करते हैं तो पहली घटना शरीर में होती है। ओएसएक्स में क्रोम पर 2-फिंगर टच के साथ परीक्षण।
जॉन्ब ३००

3

यहाँ 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/


मैंने अभी उपरोक्त कोड लागू करने वाली एक NPM लाइब्रेरी प्रकाशित की है: npmjs.com/package/dontscrollthebody
Baz Castillo

2

यहाँ मेरा समाधान है जो मैंने अनुप्रयोगों में उपयोग किया है।

मैंने बॉडी ओवरफ्लो को निष्क्रिय कर दिया और कंटेनर डिव के अंदर पूरी वेबसाइट html को रखा। वेबसाइट कंटेनरों में अतिप्रवाह होता है और इसलिए उपयोगकर्ता पृष्ठ को अपेक्षित रूप से स्क्रॉल कर सकता है।

फिर मैंने एक उच्च z-सूचकांक के साथ एक सिबलिंग डिव (#Prevent) बनाया जो पूरी वेबसाइट को कवर करता है। चूंकि #Prevent में एक उच्च z- इंडेक्स है, इसलिए यह वेबसाइट कंटेनर को ओवरलैप करता है। जब #Prevent दिखाई दे रहा है तो माउस अब वेबसाइट कंटेनरों पर मंडरा रहा है, इसलिए स्क्रॉल करना संभव नहीं है।

आप मार्कअप में #Prevent से अधिक z- इंडेक्स के साथ, निश्चित रूप से एक और div रख सकते हैं, जैसे कि आपका मोडल। यह आपको पॉप-अप विंडो बनाने की अनुमति देता है जो स्क्रॉलिंग समस्याओं से ग्रस्त नहीं हैं।

यह समाधान बेहतर है क्योंकि यह स्क्रॉलबार (कूद प्रभावित) को छिपाता नहीं है। इसे इवेंट श्रोताओं की आवश्यकता नहीं है और इसे लागू करना आसान है। यह सभी ब्राउज़रों में काम करता है, हालांकि IE7 और 8 के साथ आपको चारों ओर खेलना होगा (आपके विशिष्ट कोड पर निर्भर करता है)।

एचटीएमएल

<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>

सीएसएस

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

2
कृपया कोड पोस्ट करने के बजाय अपने उत्तर के बारे में कुछ जानकारी सहित विचार करें। हम न केवल 'सुधार' प्रदान करने की कोशिश करते हैं, बल्कि लोगों को सीखने में मदद करते हैं। आपको यह बताना चाहिए कि मूल कोड में क्या गलत था, आपने अलग-अलग क्या किया, और आपके परिवर्तन ने क्या काम किया।
एंड्रयू बार्बर

1

मुझे इस ईवेंट को कई तत्वों से जोड़ने की आवश्यकता है, जो एक स्क्रॉलबार हो सकते हैं। उन मामलों के लिए जहां कोई स्क्रॉलबार मौजूद नहीं था, मुख्य स्क्रॉलबार को उस तरह से काम नहीं करना चाहिए जैसा कि करना चाहिए। इसलिए मैंने @ codeime कोड में एक छोटा सा बदलाव किया है:

$( '.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();
    }       
});

अब, केवल स्क्रॉलबार वाले तत्व मुख्य स्क्रॉल को प्रारंभ होने से रोकेंगे।


0

विदस के जवाब का शुद्ध जावास्क्रिप्ट संस्करण, 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


0

आप इसे जावास्क्रिप्ट के बिना कर सकते हैं। आप दोनों डिव से position: fixedऔर पर स्टाइल सेट कर सकते हैं overflow-y: auto। आपको इसकी स्थापना z-index(यदि वे ओवरलैप करते हैं) करके उनमें से एक को दूसरे से अधिक बनाने की आवश्यकता हो सकती है ।

यहाँ CodePen पर एक बुनियादी उदाहरण है


0

यहां वह प्लगइन है जो एक विशिष्ट div स्क्रॉल करते समय पेरेंट स्क्रॉल को रोकने के लिए उपयोगी है और इसके साथ खेलने के लिए विकल्पों का एक गुच्छा है।

यहां इसकी जांच कीजिए:

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>

डेमो देखें


0

अगर आपको लगता है कि उपयोगकर्ता को स्पष्ट परिवर्तन पर नकारात्मक अनुभव नहीं होगा, तो इसे एक संभावित समाधान के रूप में पेश करें। मैंने बस शरीर के अतिप्रवाह के वर्ग को छिपाकर छिपा दिया जब माउस लक्ष्य डिव के ऊपर था; तब मैंने माउस के चले जाने पर शरीर की div को छिपा हुआ अतिप्रवाह में बदल दिया।

व्यक्तिगत रूप से मुझे नहीं लगता कि यह बुरा लगता है, मेरा कोड इसे क्लीनर बनाने के लिए टॉगल का उपयोग कर सकता है, और उपयोगकर्ता को जागरूक किए बिना इस प्रभाव को संभव बनाने के लिए स्पष्ट लाभ हैं। तो यह शायद हैकिश-आखिरी-रिसॉर्ट जवाब है।

//listen mouse on and mouse off for the button
pxMenu.addEventListener("mouseover", toggleA1);
pxOptContainer.addEventListener("mouseout", toggleA2);
//show / hide the pixel option menu
function toggleA1(){
  pxOptContainer.style.display = "flex";
  body.style.overflow = "hidden";
}
function toggleA2(){
  pxOptContainer.style.display = "none";
  body.style.overflow = "hidden scroll";
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.