การเลื่อน div ลูกเลื่อนหน้าต่างฉันจะหยุดได้อย่างไร


96

ฉันมี div พร้อมแถบเลื่อนเมื่อถึงจุดสิ้นสุดหน้าของฉันจะเริ่มเลื่อน ฉันจะหยุดพฤติกรรมนี้ได้หรือไม่?


2
@NGLN ไม่ใช่คำถามที่ซ้ำกันคนละคำถาม
sidewinderguy

คำตอบ:


68

คุณสามารถปิดใช้งานการเลื่อนของทั้งหน้าได้โดยทำดังนี้:

<div onmouseover="document.body.style.overflow='hidden';" onmouseout="document.body.style.overflow='auto';"></div>

33
ดี แต่มันทำให้แถบเลื่อนของเบราว์เซอร์หายไปเมื่อใดก็ตามที่คุณวางเมาส์เหนือ div
cstack

@cstack คุณพูดถูกว่าทำไม OP (Jeevan) คำตอบของตัวเองดีกว่า
Imran Bughio

2
ล้อเลื่อนของเบราว์เซอร์จำนวนมากหายไปและปรากฏขึ้นอีกครั้งโดยขึ้นอยู่กับผู้ใช้ที่เลื่อนเมาส์ในขณะนี้ดังนั้นความคิดเห็นด้านบนจึงไม่ใช่ปัญหาอีกต่อไป
Keith Holliday

วิธีนี้ใช้ไม่ได้เมื่อเพจถูกฝังใน iframe
Gautam Krishnan

5
ไม่ใช่วิธีแก้ปัญหา การตั้งค่าโอเวอร์โฟลว์เป็นซ่อนจะซ่อนแถบเลื่อนซึ่งจะฟอร์แมตเนื้อหาทั้งหมดขององค์ประกอบด้านนอกทันที นอกจากนี้ยังถือว่าองค์ประกอบด้านนอกเป็นร่างกาย แต่อาจเป็น div การเลื่อนอื่น
robisrob

43

พบวิธีแก้ปัญหา

http://jsbin.com/itajok

นี่คือสิ่งที่ฉันต้องการ

และนี่คือรหัส

http://jsbin.com/itajok/edit#javascript,html

ใช้ jQuery Plug-in


อัปเดตเนื่องจากการแจ้งเตือนการเลิกใช้งาน

จากjquery-mousewheel :

พฤติกรรมเก่าของการเพิ่มอาร์กิวเมนต์สามตัว ( delta, deltaXและdeltaY) ไปยังตัวจัดการเหตุการณ์ถูกเลิกใช้งานแล้วและจะถูกลบออกในภายหลัง

จากนั้นevent.deltaYตอนนี้ต้องใช้:

var toolbox = $('#toolbox'),
    height = toolbox.height(),
    scrollHeight = toolbox.get(0).scrollHeight;

toolbox.off("mousewheel").on("mousewheel", function (event) {
  var blockScrolling = this.scrollTop === scrollHeight - height && event.deltaY < 0 || this.scrollTop === 0 && event.deltaY > 0;
  return !blockScrolling;
});

การสาธิต


6
ลิงก์ของคุณใช้ github สำหรับ js และหยุดพักเนื่องจาก blah blah ประเภทเนื้อหาที่นี่อันนี้ใช้ได้: jsbin.com/itajok/207
Michael J. Calkins

ดูเหมือนว่า jsbins ทั้งสองจะไม่ทำงานในโปรแกรมจำลองอุปกรณ์ Chrome และบน iPhone ไม่มีใครรู้ว่ายังใช้งานได้หรือไม่?
Dirk Boer

2
"โซลูชัน" ของคุณใช้งานได้กับเหตุการณ์การเลื่อนเมาส์เท่านั้นไม่ใช่การเลื่อนหน้าขึ้น / ลงหรือปุ่มลูกศร
Scott

เหตุใดจึงต้องมี "ปิด" ที่นี่
Brad Johnson

16

โซลูชันที่เลือกคืองานศิลปะ คิดว่ามันคุ้มค่ากับปลั๊กอิน ....

$.fn.scrollGuard = function() {
    return this
        .on( 'wheel', function ( e ) {
            var event = e.originalEvent;
            var d = event.wheelDelta || -event.detail;
            this.scrollTop += ( d < 0 ? 1 : -1 ) * 30;
            e.preventDefault();
        });
};    

นี่เป็นความไม่สะดวกอย่างต่อเนื่องสำหรับฉันและโซลูชันนี้สะอาดมากเมื่อเทียบกับแฮ็กอื่น ๆ ที่ฉันเคยเห็น อยากรู้ว่ามันทำงานอย่างไรและจะได้รับการสนับสนุนอย่างกว้างขวางแค่ไหน แต่ขอเชียร์ Jeevan และใครก็ตามที่คิดเรื่องนี้ BTW - โปรแกรมแก้ไขคำตอบ stackoverflow ต้องการสิ่งนี้!

อัปเดต

ฉันเชื่อว่าสิ่งนี้ดีกว่าที่จะไม่พยายามจัดการ DOM เลยเพียง แต่ป้องกันการเกิดฟองตามเงื่อนไข ...

$.fn.scrollGuard2 = function() {
  return this
    .on( 'wheel', function ( e ) {
      var $this = $(this);
      if (e.originalEvent.deltaY < 0) {
        /* scrolling up */
        return ($this.scrollTop() > 0);
      } else {
        /* scrolling down */
        return ($this.scrollTop() + $this.innerHeight() < $this[0].scrollHeight);
      }
    })
  ;
};    

ใช้งานได้ดีใน Chrome และง่ายกว่าโซลูชันอื่น ๆ มาก ... แจ้งให้เราทราบว่าค่าโดยสารที่อื่นเป็นอย่างไร ...

ซอ


3
การเพิ่มเหตุการณ์ DOMMouseScroll ทำให้ใช้งานได้กับ Firefox → jsfiddle.net/chodorowicz/egqy7mbz/1
chodorowicz

ฉันแปลกใจที่ไม่ได้เขียนลงใน jquery ฉันคิดว่าหนึ่งในประเด็นหลักคือไม่ต้องสนใจว่าคุณกำลังใช้เบราว์เซอร์ใดอยู่
robisrob

ดูเหมือนว่าทั้งคู่จะเลิกใช้แล้ว ... wheelevent
robisrob

ซึ่งส่งผลให้การเลื่อนใน Chrome บน Macbook ของฉันกระตุกขึ้นอย่างเห็นได้ชัด วิธีการแก้ปัญหาที่ยอมรับไม่มีปัญหานี้
danvk

น่าผิดหวัง. มีเวอร์ชันที่แตกต่างกันมากมาย ดูเหมือนเป็นสิ่งสำคัญของ ui และน่าแปลกใจที่นี่เป็นพฤติกรรมเริ่มต้นเมื่อมันไม่ได้ตั้งใจ เห็นได้ชัดว่าเบราว์เซอร์ได้รับการติดตั้งเพื่อให้ทราบว่า div การเลื่อนด้านในมีขีด จำกัด ที่จะสามารถใช้เหตุการณ์กับหน้าต่างแทนได้ดังนั้นทำไมจึงไม่มีที่จับสำหรับค้นหา
robisrob

8

คุณสามารถใช้เหตุการณ์การวางเมาส์บน div เพื่อปิดใช้งานแถบเลื่อนเนื้อหาจากนั้นเหตุการณ์เมาส์เอาท์เพื่อเปิดใช้งานอีกครั้ง?

เช่น HTML

<div onmouseover="disableBodyScroll();" onmouseout="enableBodyScroll();">
    content
</div>

แล้วจาวาสคริปต์ก็เป็นเช่นนั้น:

var body = document.getElementsByTagName('body')[0];
function disableBodyScroll() {
    body.style.overflowY = 'hidden';
}
function enableBodyScroll() {
    body.style.overflowY = 'auto';
}

12
คุณสามารถใช้document.bodyแทนได้เช่นกัน
Ry-

8

ต่อไปนี้เป็นวิธีข้ามเบราว์เซอร์ในแกน Y ซึ่งใช้ได้ทั้งบนเดสก์ท็อปและมือถือ ทดสอบบน OSX และ iOS

var scrollArea = this.querySelector(".scroll-area");
scrollArea.addEventListener("wheel", function() {
    var scrollTop = this.scrollTop;
    var maxScroll = this.scrollHeight - this.offsetHeight;
    var deltaY = event.deltaY;
    if ( (scrollTop >= maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
        event.preventDefault();
    }
}, {passive:false});

scrollArea.addEventListener("touchstart", function(event) {
    this.previousClientY = event.touches[0].clientY;
}, {passive:false});

scrollArea.addEventListener("touchmove", function(event) {
    var scrollTop = this.scrollTop;
    var maxScroll = this.scrollHeight - this.offsetHeight;
    var currentClientY = event.touches[0].clientY;
    var deltaY = this.previousClientY - currentClientY;
    if ( (scrollTop >= maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
        event.preventDefault();
    }
    this.previousClientY = currentClientY;
}, {passive:false});

ใช้งานได้ยอดเยี่ยม! ว้าวสิ่งที่ฉันค้นหา ต้องการการโหวตเพิ่มขึ้นอย่างแน่นอน
delato468

การแก้ปัญหานี้ทำงานสวยดี แต่ต้องปรับเล็ก ๆ น้อย ๆ : จำเป็นที่จะต้องเปลี่ยนจากscrollTop === maxScroll scrollTop >= maxScrollดูเหมือนว่าจะแปลกใน 1 กรณีจำเป็น
tchiot.ludo

7

ฉันเขียนว่าแก้ไขปัญหานี้แล้ว

  var div;
  div = document.getElementsByClassName('selector')[0];

  div.addEventListener('mousewheel', function(e) {
    if (div.clientHeight + div.scrollTop + e.deltaY >= div.scrollHeight) {
      e.preventDefault();
      div.scrollTop = div.scrollHeight;
    } else if (div.scrollTop + e.deltaY <= 0) {
      e.preventDefault();
      div.scrollTop = 0;
    }
  }, false);

หนึ่งในวิธีแก้ปัญหาไม่กี่วิธีที่ใช้งานได้โดยไม่มีองค์ประกอบของหน้ากระโดดอย่างน่ารำคาญเนื่องจากมีการตั้งค่าส่วนเกินที่ซ่อนอยู่
ขี้ระแวง

+1 นี่คือทางออกที่มั่นคง ถ้าคุณแนบนี้ภาชนะเลื่อนคุณจะต้องการ div e.currentTargetในตัวอย่างนี้จะเป็น
Matt

น้ำยาสะอาดมาก ขอบคุณ
Thinh Bui

ทำงานใน Chrome 61.0.3163.100 และ Safari 11.0 แต่ไม่ใช่ใน FireFox 56.0 (Mac OS El Capitan)
BigJ

นี่คือโซลูชันดั้งเดิมที่ดีที่สุด อย่างไรก็ตามfalseไม่จำเป็นต้องระบุaddEventListenerเนื่องจากเป็นค่าเริ่มต้น นอกจากนี้การเปรียบเทียบที่ควรจะเป็นความไม่เท่าเทียมกันง่าย ( >และ<) ไม่ใช่หรือ>= <=
คำถาม Quolonel

7

ตามคำตอบที่นี่เบราว์เซอร์ที่ทันสมัยส่วนใหญ่รองรับoverscroll-behavior: none;คุณสมบัติ CSS ซึ่งป้องกันไม่ให้มีการเลื่อนโซ่ เพียงแค่บรรทัดเดียวเท่านั้น!


2
นี้ควรจะเป็นคำตอบที่ถูกต้องในปี 2020 overscroll-behavior: contain;สำหรับกรณีการใช้งานของฉันวิธีการแก้ปัญหาที่ดีที่สุดคือ
ท่าเรือ

สิ่งนี้ไม่ได้รับการสนับสนุนอย่างสมบูรณ์สำหรับขอบบางรุ่น มีความคิดอย่างไรในการแก้ปัญหานี้ด้วยวิธีอื่น
YTG

6

ถ้าฉันเข้าใจคำถามของคุณอย่างถูกต้องคุณจะต้องป้องกันไม่ให้เลื่อนเนื้อหาหลักเมื่อเมาส์อยู่เหนือ div (สมมติว่าเป็นแถบด้านข้าง) ด้วยเหตุนี้แถบด้านข้างอาจไม่ใช่ลูกของคอนเทนเนอร์การเลื่อนของเนื้อหาหลัก (ซึ่งก็คือหน้าต่างเบราว์เซอร์) เพื่อป้องกันไม่ให้เหตุการณ์การเลื่อนไหลไปที่ระดับบนสุด

อาจต้องมีการเปลี่ยนแปลงมาร์กอัปบางอย่างในลักษณะต่อไปนี้:

<div id="wrapper"> 
    <div id="content"> 
    </div> 
</div> 
<div id="sidebar"> 
</div> 

ดูว่ามันใช้งานได้ในซอตัวอย่างนี้และเปรียบเทียบกับซอตัวอย่างนี้ซึ่งมีพฤติกรรมการปล่อยเมาส์ที่แตกต่างกันเล็กน้อยของแถบด้านข้าง

ดูเพิ่มเติมเลื่อนเพียงหนึ่ง div โดยเฉพาะอย่างยิ่งกับการเลื่อนหลักเบราว์เซอร์


ในกรณีนี้แถบด้านข้างจะอยู่นอก wrapper div ดังนั้นฉันไม่คิดว่าม้วนหนังสือจะส่งถึงผู้ปกครอง
Jeevan

โดย "กรณีนี้" คุณหมายถึงกรณีของคุณหรือไม่? ถ้าไม่: คุณพูดถูก หากเป็นเช่นนั้น: หากหน้าของคุณเลื่อนไปที่ส่วนท้ายของการเลื่อน div ข้อความเลื่อนจะปรากฏขึ้นไปยัง div พาเรนต์ดังนั้นฉันคิดว่าเพจและ div ของคุณไม่ใช่พี่น้องกัน แต่เป็นพาเรนต์และรอง
NGLN

ใช่เพจคือพาเรนต์ของ div ของฉันดังนั้นเมื่อไปถึงจุดสิ้นสุดมันจะเริ่มเลื่อนหน้าซึ่งฉันไม่ต้องการ
Jeevan

หากคุณไม่สามารถทำให้ div ของคุณเป็นพี่น้องของเนื้อหาหลักปัญหานี้จะไม่สามารถแก้ไขได้ด้วย HTML + CSS เพียงอย่างเดียว เป็นพฤติกรรมเริ่มต้น
NGLN

1
ฉันคิดว่านี่เป็นวิธีแก้ปัญหาที่มีประสิทธิภาพที่สุดในบรรดาคำตอบที่มีให้ทั้งหมด ด้วยมาร์กอัปที่ดีที่ฐานของเพจจำเป็นต้องใช้ CSS และแฮ็ก JS น้อยกว่ามากเพื่อให้ได้พฤติกรรมที่ต้องการ

3

สิ่งนี้จะปิดใช้งานการเลื่อนบนหน้าต่างหากคุณเข้าสู่องค์ประกอบตัวเลือก ทำงานเหมือนเสน่ห์

elements = $(".selector");

elements.on('mouseenter', function() {
    window.currentScrollTop = $(window).scrollTop();
    window.currentScrollLeft = $(window).scrollTop();
    $(window).on("scroll.prevent", function() {
        $(window).scrollTop(window.currentScrollTop);
        $(window).scrollLeft(window.currentScrollLeft);
    });
});

elements.on('mouseleave', function() {
    $(window).off("scroll.prevent");
});

นี่เป็นวิธีแก้ปัญหาที่ใช้ได้ผลจริง ฉันต้องการมันใน js บริสุทธิ์ดังนั้นฉันจึงเขียนมันใหม่ ถ้าใครต้องการมันก็ที่นี่ สำหรับทุกคนที่ยังคงมองหาวิธีการแก้ปัญหาที่คุณควรตรวจสอบคำตอบของฉันด้านล่าง
Andriy Stolyar

2

คุณสามารถปิดการใช้งานการเลื่อนของทั้งหน้าได้โดยทำสิ่งนี้ แต่แสดงแถบเลื่อน!

<div onmouseover="document.body.style.overflow='hidden'; document.body.style.position='fixed';" onmouseout="document.body.style.overflow='auto'; document.body.style.position='relative';"></div>

2
$this.find('.scrollingDiv').on('mousewheel DOMMouseScroll', function (e) {
  var delta = -e.originalEvent.wheelDelta || e.originalEvent.detail;
  var scrollTop = this.scrollTop;
  if((delta < 0 && scrollTop === 0) || (delta > 0 && this.scrollHeight - this.clientHeight - scrollTop === 0)) {
    e.preventDefault();
  }
});

1

จากคำตอบของ ceed นี่คือเวอร์ชันที่อนุญาตให้มีองค์ประกอบที่มีการป้องกันการเลื่อนซ้อนกัน เฉพาะองค์ประกอบที่เมาส์อยู่เท่านั้นที่จะเลื่อนและเลื่อนได้ค่อนข้างราบรื่น เวอร์ชันนี้ยังมีผู้เข้าร่วมอีกครั้ง สามารถใช้หลายครั้งในองค์ประกอบเดียวกันและจะลบและติดตั้งเครื่องจัดการใหม่อย่างถูกต้อง

jQuery.fn.scrollGuard = function() {
    this
        .addClass('scroll-guarding')
        .off('.scrollGuard').on('mouseenter.scrollGuard', function() {
            var $g = $(this).parent().closest('.scroll-guarding');
            $g = $g.length ? $g : $(window);
            $g[0].myCst = $g.scrollTop();
            $g[0].myCsl = $g.scrollLeft();
            $g.off("scroll.prevent").on("scroll.prevent", function() {
                $g.scrollTop($g[0].myCst);
                $g.scrollLeft($g[0].myCsl);
            });
        })
        .on('mouseleave.scrollGuard', function() {
            var $g = $(this).parent().closest('.scroll-guarding');
            $g = $g.length ? $g : $(window);
            $g.off("scroll.prevent");
        });
};

วิธีใช้ง่ายๆวิธีหนึ่งคือเพิ่มคลาสเช่นscroll-guardองค์ประกอบทั้งหมดในหน้าที่คุณอนุญาตให้เลื่อนได้ แล้วใช้$('.scroll-guard').scrollGuard()เพื่อป้องกันพวกเขา


0

หากคุณใช้overflow: hiddenสไตล์มันควรจะหายไป

แก้ไข: ที่จริงฉันอ่านคำถามของคุณผิดซึ่งจะซ่อนเฉพาะแถบเลื่อน แต่ฉันไม่คิดว่านั่นคือสิ่งที่คุณกำลังมองหา


1
ฉันต้องการทั้งแถบเลื่อน กำลังพูดถึงพฤติกรรม เมื่อฉันเลื่อนโดยใช้แทร็กบอลของเมาส์เมื่อไปถึงจุดสิ้นสุดของการเลื่อนของ div จะต้องไม่เลื่อนทั้งหน้า
Jeevan

0

ฉันไม่ได้รับคำตอบใด ๆ ในการทำงานใน Chrome และ Firefox ดังนั้นฉันจึงได้ทำการควบรวมนี้:

$someElement.on('mousewheel DOMMouseScroll', scrollProtection);

function scrollProtection(event) {
    var $this = $(this);
    event = event.originalEvent;
    var direction = (event.wheelDelta * -1) || (event.detail);
    if (direction < 0) {
        if ($this.scrollTop() <= 0) {
            return false;
        }
    } else {
        if ($this.scrollTop() + $this.innerHeight() >= $this[0].scrollHeight) {
            return false;
        }
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.