acara gulir javascript untuk iPhone / iPad?

107

Sepertinya saya tidak bisa menangkap acara gulir di iPad. Tak satu pun dari ini berhasil, apa yang saya lakukan salah?

window.onscroll=myFunction;

document.onscroll=myFunction;

window.attachEvent("scroll",myFunction,false);

document.attachEvent("scroll",myFunction,false);

Semuanya bekerja bahkan di Safari 3 di Windows. Ironisnya, SETIAP browser di PC mendukung window.onload=jika Anda tidak keberatan mengganggu acara yang ada. Tapi jangan pergi di iPad.

ck_
sumber

Jawaban:

146

IPhoneOS memang merekam onscrollacara, kecuali tidak seperti yang Anda harapkan.

Penggeseran satu jari tidak menghasilkan peristiwa apa pun hingga pengguna berhenti menggeser — onscrollperistiwa dibuat saat halaman berhenti bergerak dan menggambar ulang — seperti yang ditunjukkan pada Gambar 6-1.

Demikian pula, gulir dengan 2 jari aktif onscrollhanya setelah Anda berhenti menggulir.

Cara biasa memasang handler bekerja mis

window.addEventListener('scroll', function() { alert("Scrolled"); });
// or
$(window).scroll(function() { alert("Scrolled"); });
// or
window.onscroll = function() { alert("Scrolled"); };
// etc 

(Lihat juga https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html )

kennytm
sumber
23
Terima kasih, hal itu memaksa saya untuk melihat masalahnya lebih jauh. Jawaban sebenarnya adalah mendeteksi bagian atas viewport pada iphone / ipad hanya bekerja dengan window.pageYOffset dan tidak document.body.scrollTop||document.documentElement.scrollTop seperti semua browser / perangkat keras lain yang ada.
ck_
6
@ck_ Sayangnya di iPad window.pageYOffsettidak diperbarui dalam fase perlambatan, tetapi hanya ketika gulir selesai.
Adaptabi
2
Menimpa window.onscroll secara langsung merupakan praktik yang buruk. Menambahkan pendengar acara akan lebih baik. Gunakan window.addEventListener ('scroll', function () {alert ('scrolled!');});
Kevin Dice
4
ehm .. sebenarnya, window.onscroll aktif di ipad saya setiap saat, saat menggeser, dan setelah menggeser, saat melambat. apakah ada yang berubah?
commonpike
Safari (dan mungkin yang lain) berubah menjadi menggunakan WKWebView dengan iOS 8. Chrome dan Cordova masih menggunakan UIWebView, jadi mereka masih menunjukkan masalah dengan peristiwa gulir berkelanjutan yang tidak dikeluarkan. Ada plug-in WKWebView untuk Cordova.
jiku
105

Untuk iOS Anda perlu menggunakan acara touchmove serta acara gulir seperti ini:

document.addEventListener("touchmove", ScrollStart, false);
document.addEventListener("scroll", Scroll, false);

function ScrollStart() {
    //start of scroll event for iOS
}

function Scroll() {
    //end of scroll event for iOS
    //and
    //start/end of scroll event for other browsers
}
George Filippakos
sumber
37
Peristiwa ini hanya diaktifkan saat pengguna menggulir secara aktif, dan tidak diaktifkan selama fase perlambatan pengguliran momentum.
Jon Tirsen
saya mengubah kode untuk menyertakan kode deteksi gulir akhir untuk iOS
George Filippakos
Anda mungkin juga ingin menambahkan listener untuk "touchend" yang akan bertindak mirip dengan scroll di desktop.
BingeBoy
1
Perhatikan bahwa ini tidak menyediakan akses ke selama fase gulir
Ben Sewards
3
sudah tiga tahun. Saya tidak bisa mendapatkan pembaruan posisi gulir secara realtime selama perlambatan. bagaimana saya bisa menulis aplikasi seperti peta ?????
FlavorScape
38

Maaf telah menambahkan jawaban lain ke posting lama tetapi saya biasanya mendapatkan acara gulir dengan sangat baik dengan menggunakan kode ini (berfungsi setidaknya pada 6.1)

element.addEventListener('scroll', function() {
    console.log(this.scrollTop);
});

// This is the magic, this gives me "live" scroll events
element.addEventListener('gesturechange', function() {});

Dan itu berhasil untuk saya. Satu-satunya hal yang tidak dilakukannya adalah memberikan acara gulir untuk perlambatan gulir (Setelah perlambatan selesai Anda mendapatkan acara gulir terakhir, lakukan apa yang Anda inginkan.) Tetapi jika Anda menonaktifkan inersia dengan css dengan melakukan ini

-webkit-overflow-scrolling: none;

Anda tidak mendapatkan inersia pada elemen Anda, untuk tubuh Anda mungkin harus melakukan yang klasik

document.addEventListener('touchmove', function(e) {e.preventDefault();}, true);
Dave Mackintosh
sumber
7
Mengapa memberi suara negatif pada jawaban yang valid dan tidak meninggalkan komentar yang menjelaskan masalahnya?
Dave Mackintosh
3
karena downvoting itu mudah dan cepat. : /
Zeshan Ahmed
5
Sebuah jawaban SELALU "valid" menurut pembuatnya ... Tidak ada yang memposting jawaban yang secara sengaja tidak valid. Tapi ya, mereka seharusnya menjelaskan mengapa mereka menurunkan suara.
Matthieu Charbonnier
3
gesturechangeacara tidak standar dan hanya didukung oleh Safari: developer.mozilla.org/en-US/docs/Web/Events/gesturechange
Nicolas Bouvrette
6

Saya bisa mendapatkan solusi hebat untuk masalah ini dengan iScroll, dengan nuansa momentum scrolling dan semuanya https://github.com/cubiq/iscroll Doc github hebat, dan saya kebanyakan mengikutinya. Berikut detail implementasi saya.

HTML: Saya membungkus area konten saya yang dapat digulir dalam beberapa div yang dapat digunakan oleh iScroll:

<div id="wrapper">
  <div id="scroller">
    ... my scrollable content
  </div>
</div>

CSS: Saya menggunakan kelas Modernizr untuk "sentuh" ​​untuk menargetkan perubahan gaya saya hanya untuk perangkat sentuh (karena saya hanya membuat contoh iScroll saat disentuh).

.touch #wrapper {
  position: absolute;
  z-index: 1;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  overflow: hidden;
}
.touch #scroller {
  position: absolute;
  z-index: 1;
  width: 100%;
}

JS: Saya menyertakan iscroll-probe.js dari unduhan iScroll, dan kemudian menginisialisasi scroller seperti di bawah ini, di mana updatePosition adalah fungsi saya yang bereaksi terhadap posisi scroll baru.

# coffeescript
if Modernizr.touch
  myScroller = new IScroll('#wrapper', probeType: 3)
  myScroller.on 'scroll', updatePosition
  myScroller.on 'scrollEnd', updatePosition

Anda harus menggunakan myScroller untuk mendapatkan posisi saat ini, daripada melihat scroll offset. Ini adalah fungsi yang diambil dari http://markdalgleish.com/presentations/embracingtouch/ (artikel yang sangat membantu, tapi agak ketinggalan zaman sekarang)

function getScroll(elem, iscroll) {   
  var x, y;

  if (Modernizr.touch && iscroll) {
    x = iscroll.x * -1;
    y = iscroll.y * -1;   
  } else {
    x = elem.scrollTop;
    y = elem.scrollLeft;   
  }

  return {x: x, y: y}; 
}

Satu-satunya gotcha lain adalah kadang-kadang saya akan kehilangan bagian dari halaman saya yang saya coba gulir, dan itu akan menolak untuk menggulir. Saya harus menambahkan beberapa panggilan ke myScroller.refresh () setiap kali saya mengubah konten #wrapper, dan itu menyelesaikan masalah.

EDIT: Gotcha lain adalah bahwa iScroll memakan semua acara "klik". Saya mengaktifkan opsi agar iScroll mengeluarkan acara "ketuk" dan menanganinya alih-alih acara "klik". Untungnya saya tidak perlu banyak mengklik di area gulir, jadi ini bukan masalah besar.

Melinda Weathers
sumber
1

Sejak iOS 8 keluar, masalah ini tidak ada lagi. Acara gulir sekarang juga dijalankan dengan lancar di Safari iOS.

Jadi, jika Anda mendaftarkan scrollevent handler dan memeriksa window.pageYOffsetdi dalam event handler itu, semuanya bekerja dengan baik.

Matthias Bohlen
sumber
1
Itu belum ada dalam beberapa kasus penggunaan seperti menggunakan Cordova. developer.telerik.com/featured/…
diosney
6
Pengalaman saya adalah bahwa ini masih menjadi masalah dengan perangkat iOS saat ini pada tahun 2019.
Chris