จะรับตำแหน่ง scrollbar ด้วย Javascript ได้อย่างไร


191

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

คำตอบ:


210

คุณสามารถใช้element.scrollTopและelement.scrollLeftเพื่อให้ได้ offset ในแนวตั้งและแนวนอนตามลำดับที่ถูกเลื่อน elementอาจเป็นdocument.bodyถ้าคุณใส่ใจกับทั้งหน้า คุณสามารถเปรียบเทียบกับelement.offsetHeightและelement.offsetWidth( elementอาจเป็นร่างกาย) อีกครั้งหากคุณต้องการเปอร์เซ็นต์


2
สิ่งที่เบราว์เซอร์ที่คุณใช้? การทำให้เนื้อหานั้นแตกต่างกันไปในเบราว์เซอร์ที่ต่างกัน ( elementและdocument.bodyเป็นเพียงตัวอย่าง) ดูhowtocreate.co.uk/tutorials/javascript/browserwindowสำหรับรายละเอียด
Max Shawabkeh

8
ฉันได้รับเพื่อให้ค่าที่ถูกต้องกับ Firefox 3.6 ด้วยwindow.pageYOffsetแต่ไม่สามารถทำงานอะไรกับ IE7 ได้ พยายามwindow.pageYOffset, document.body.scrollTop, document.documentElement.scrollTop,element.scrollTop
พอล

1
scrollTop ใช้งานได้เฉพาะกับฉันเมื่อฉันเพิ่มวงเล็บ ... $ (". scrollBody"). scrollTop ()
maia

9
หากคุณกำลังเผชิญกับองค์ประกอบ 'หน้าต่าง' คุณอาจใช้ window.scrollY แทน window.scrollTop
Janis Jansen

6
ผมคิดว่าเลื่อนตำแหน่งไม่ได้ตั้งอยู่บนdocument.bodyเบราว์เซอร์ที่ทันสมัยที่สุด - มันมักจะตั้งอยู่บนdocument.documentElementในขณะนี้ ดูbugs.chromium.org/p/chromium/issues/detail?id=157855สำหรับการเปลี่ยนผ่านของ Chrome
fzzfzzfzz

134

ฉันทำสิ่งนี้เพื่อ<div>บน Chrome

องค์ประกอบ. scrollTop - เป็นพิกเซลที่ซ่อนอยู่ด้านบนอันเนื่องมาจากการเลื่อน ไม่มีการเลื่อนค่าของมันคือ 0

องค์ประกอบ. scrollHeight - เป็นพิกเซลของ div ทั้งหมด

องค์ประกอบ . clientHeight - เป็นพิกเซลที่คุณเห็นในเบราว์เซอร์ของคุณ

var a = element.scrollTop;

จะเป็นตำแหน่ง

var b = element.scrollHeight - element.clientHeight;

จะเป็นสูงสุดค่าสำหรับscrollTop

var c = a / b;

จะเป็นเปอร์เซ็นต์ของเลื่อน[0-1]


3
นี่เกือบจะถูกต้องแล้ว สำหรับ var b คุณควรจะลบ window.innerHeight ไม่ใช่ element.clientHeight
Kahless

51
document.getScroll = function() {
    if (window.pageYOffset != undefined) {
        return [pageXOffset, pageYOffset];
    } else {
        var sx, sy, d = document,
            r = d.documentElement,
            b = d.body;
        sx = r.scrollLeft || b.scrollLeft || 0;
        sy = r.scrollTop || b.scrollTop || 0;
        return [sx, sy];
    }
}

ส่งคืนอาร์เรย์ที่มีจำนวนเต็มสองจำนวน - [scrollLeft, scrollTop]


4
แสดงวิธีใช้ฟังก์ชั่นนี้พร้อมกับตัวอย่างจะดีมาก
user18490

1
ฉันเดาว่าคุณสามารถใช้ lastscroll นี้ = getScroll (); window.scrollTo (lastscroll [0], lastscroll [1]);
Dinesh Rajan

ใช้งานได้ดี แต่ฉันเปลี่ยนกลับไปเป็นวัตถุด้วยปุ่ม x และ y เนื่องจากนั่นทำให้ฉันมีความรู้สึกมากกว่าเล็กน้อย
xd6_

แก้ไขตามความคิดเห็นของ @ user18490 แล้ว
Davide Cannizzo

ReferenceError: ไม่พบตัวแปร: องค์ประกอบ
จอนนี่


11

คำตอบสำหรับปี 2018 :

วิธีที่ดีที่สุดที่จะทำสิ่งที่ชอบคือการใช้แยกสังเกตการณ์ API

Intersection Observer API ให้วิธีการแบบอะซิงโครนัสสังเกตการเปลี่ยนแปลงในการแยกขององค์ประกอบเป้าหมายด้วยองค์ประกอบบรรพบุรุษหรือด้วยวิวพอร์ตของเอกสารระดับบนสุด

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

  • การโหลดรูปภาพหรือเนื้อหาอื่น ๆ อย่างขี้เกียจเมื่อเลื่อนหน้า
  • การใช้งานเว็บไซต์ "เลื่อนไม่สิ้นสุด" ซึ่งมีการโหลดและแสดงเนื้อหามากขึ้นเรื่อย ๆ เมื่อคุณเลื่อนเพื่อให้ผู้ใช้ไม่ต้องพลิกหน้า
  • การรายงานการเปิดเผยโฆษณาเพื่อคำนวณรายได้โฆษณา
  • การตัดสินใจว่าจะปฏิบัติงานหรือกระบวนการแอนิเมชั่นหรือไม่ขึ้นอยู่กับว่าผู้ใช้จะเห็นผลลัพธ์หรือไม่

การนำการตรวจจับทางแยกในอดีตเกี่ยวข้องกับตัวจัดการเหตุการณ์และวิธีการเรียกวนรอบเช่น Element.getBoundingClientRect () เพื่อสร้างข้อมูลที่จำเป็นสำหรับทุกองค์ประกอบที่ได้รับผลกระทบ เนื่องจากรหัสทั้งหมดนี้ทำงานบนเธรดหลักแม้แต่หนึ่งในนั้นอาจทำให้เกิดปัญหาประสิทธิภาพการทำงาน เมื่อไซต์เต็มไปด้วยการทดสอบเหล่านี้สิ่งต่างๆอาจดูน่าเกลียดอย่างสิ้นเชิง

ดูตัวอย่างรหัสต่อไปนี้:

var options = {
  root: document.querySelector('#scrollArea'),
  rootMargin: '0px',
  threshold: 1.0
}

var observer = new IntersectionObserver(callback, options);

var target = document.querySelector('#listItem');
observer.observe(target);

เบราว์เซอร์ที่ทันสมัยส่วนใหญ่รองรับ IntersectionObserverแต่คุณควรใช้polyfillเพื่อความเข้ากันได้แบบย้อนหลัง



3

หากคุณใช้ jQuery มีฟังก์ชั่นที่สมบูรณ์แบบสำหรับคุณ: .scrollTop ()

เอกสารที่นี่ -> http://api.jquery.com/scrollTop/

หมายเหตุ: คุณสามารถใช้ฟังก์ชั่นนี้เพื่อดึงข้อมูลหรือตั้งค่าตำแหน่ง

ดูเพิ่มเติมได้ที่: http://api.jquery.com/?s=scroll


25
ทำไมต้องตอบคำถามเกี่ยวกับ JS ที่มีไลบรารี่สำหรับ JS เมื่อมันเป็นไปได้อย่างสมบูรณ์และสะดวกที่จะทำใน JS ดิบ? คุณแค่ขอให้เขาเพิ่มเวลาโหลดเพิ่มรวมถึงใช้พื้นที่เก็บข้อมูลบางอย่างเพื่อสิ่งที่ไม่จำเป็นโดยสิ้นเชิง นอกจากนี้ตั้งแต่เมื่อใดที่จาวาสคริปต์เริ่มหมายถึง JQuery
DaemonOfTheWest

4
หากคุณถามเป็นรายบุคคลฉันไม่เคยชอบ jQuery และฉันยังไม่ได้ตอบคำถามนี้ แต่ใน Vanilla JS มีคำตอบจากเพื่อนคนอื่น ๆ อยู่แล้วปัญหาจะเกิดอะไรขึ้นถ้ามีใครบางคนเพิ่มเครื่องเทศอร่อย ๆ ในกระทู้นี้ คุณกำลังใช้ jQuery)
Ravinder Payal

@ R01010010 เป็นเพราะตอนนี้ JQuery ไม่มีประโยชน์และไม่ได้ผลคุณลักษณะทั้งหมดจาก JQuery นั้นติดตั้งได้ง่ายกับ VanilaJS และคุณยังต้องพึ่งพาสิ่งที่อยู่ใน JQuery ด้วยคุณสมบัติใหม่ที่มีอยู่ใน VanillsaJS คุณเป็นโปรแกรมเมอร์ไม่อัปเดต ตอนนี้วันที่มี API ใหม่ใน VanillaJS เรียกว่า fetch ที่แทนที่ XHR เก่าถ้าคุณเพิ่งอยู่ในโลกของ JQuery จะไม่เห็นประโยชน์ในการดึงและใช้ jQuery.ajax ต่อไป () ความเห็นส่วนตัวของฉันคือคนที่ดำเนินการต่อไป การใช้ JQuery เป็นเพราะพวกเขาหยุดเรียนรู้ นอกจากนี้ VanillaJS ยังเร็วกว่า vanilla-js.com
John Balvin Arias

@JohnBalvinArias กำลังพูดถึงการดึงข้อมูลเกิดอะไรขึ้นกับ IE11 หรือแม้แต่ Edge
เบ็น

แก้ไขให้ฉันถ้าฉันผิด แต่การดึงข้อมูลไม่ทำงานอย่างถูกต้องกับ "สมัยใหม่" และนั่นคือยังคงใช้กันอย่างแพร่หลาย ถ้าฉันใช้ jquery ฉันก็แทบจะไม่ได้รับการกระตุ้นให้ทำต่อไป
เบ็น

3

นี่คือวิธีอื่นในการรับตำแหน่งการเลื่อน

const getScrollPosition = (el = window) => ({
  x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
  y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
});

0

ฉันคิดว่าฟังก์ชั่นต่อไปนี้สามารถช่วยให้มีค่าพิกัดเลื่อน:

const getScrollCoordinate = (el = window) => ({
  x: el.pageXOffset || el.scrollLeft,
  y: el.pageYOffset || el.scrollTop,
});

ฉันได้รับแนวคิดนี้จากคำตอบนี้ด้วยการเปลี่ยนแปลงเล็กน้อย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.