iPhone / iPadのJavaScriptスクロールイベント?


107

iPadでスクロールイベントをキャプチャできないようです。これらのどれも動作しません、私は何を間違っていますか?

window.onscroll=myFunction;

document.onscroll=myFunction;

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

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

これらはすべてWindows上のSafari 3でも機能します。皮肉なことに、PC上のwindow.onload=すべてのブラウザーは、既存のイベントを壊してかまわない場合にサポートされます。しかし、iPadで行くことはできません。

回答:


146

iPhoneOSはonscrollイベントをキャプチャしますが、予想した方法とは異なります。

onscroll図6-1に示すように、1本指のパンでは、ユーザーがパンを停止する(ページの移動と再描画が停止するとイベントが生成される)まで、イベントは生成されません。

同様に、2本指でのスクロールは、スクロールをonscroll停止した後にのみ発生します。

ハンドラーをインストールする通常の方法は機能します。

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

https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.htmlも参照してください


23
おかげで、私は問題をさらに調査することを余儀なくされました。本当の答えは、iPhone / iPadのビューポートの上部を検出することは、 他のすべてのブラウザ/ハードウェアwindow.pageYOffset とは 異なり、動作するだけ document.body.scrollTop||document.documentElement.scrollTopです。
ck_

6
IPADの@ck_ Unfortunatelly window.pageYOffsetは、減速フェーズでは更新されませんが、スクロールが終了したときにのみ更新されます。
Adaptabi

2
window.onscrollを直接上書きすることは悪い習慣です。イベントリスナーを追加した方がいいでしょう。window.addEventListener( 'scroll'、function(){alert( 'scrolled!');});を使用します。
Kevin Dice 14

4
ehm ..実際、window.onscrollは、パン中、およびパン後の減速中に、常にipadで発火しています。何か変わった?
commonpike 2015

Safari(およびその他)は、iOS 8でWKWebViewを使用するように変更されました。ChromeとCordovaは引き続きUIWebViewを使用するため、継続的なスクロールイベントが発行されないという問題が引き続き発生します。CordovaにはWKWebViewプラグインがあります。
jiku

105

iOSの場合は、touchmoveイベントとscrollイベントを次のように使用する必要があります。

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
}

37
このイベントは、ユーザーがアクティブにスクロールしているときにのみ発生し、モーメンタムスクロールの減速フェーズでは発生しません。
Jon Tirsen、2012年

iOS用のスクロール終了検出コードを含めるようにコードを変更しました
George Filippakos

デスクトップでのスクロールと同様に機能する「touchend」のリスナーを追加することもできます。
BingeBoy 2014

1
これはスクロールフェーズ中のアクセスを提供しないことに注意してください
Ben Sewards 2015

3
3年になります。減速中にスクロール位置のリアルタイム更新を取得できません。マップのようなアプリを作成するにはどうすればよいですか?????
FlavorScape 2016年

38

古い投稿に別の回答を追加して申し訳ありませんが、私は通常、このコードを使用してスクロールイベントを非常にうまく取得します(少なくとも6.1で機能します)。

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

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

そして、それは私にとってはうまくいきます。それがしない唯一のことは、スクロールの減速のためにスクロールイベントを与えることです(減速が完了したら、最終的なスクロールイベントを取得します、それを行うのと同じようにしてください)。

-webkit-overflow-scrolling: none;

あなたは古典的なことをしなければならないかもしれませんが、身体のために、あなたの要素に慣性を得ません

document.addEventListener('touchmove', function(e) {e.preventDefault();}, true);

7
なぜ有効な回答に反対票を投じ、それに関する問題を説明するコメントを残さないのですか?
Dave Mackintosh 2014年

3
反対投票は簡単かつ迅速だからです。:/
Zeshan Ahmed 2016

5
その作者によれば、答えは常に「有効」です...故意に無効な答えを投稿する人はいません。しかし、はい、彼らはなぜ彼らが反対票を投じたのか説明すべきでした。
Matthieu Charbonnier

3
gesturechangeイベントは非標準であり、Safariでのみサポートされています:developer.mozilla.org/en-US/docs/Web/Events/gesturechange
Nicolas Bouvrette

6

私は運動量スクロールし、すべての感覚で、iScrollで、この問題に対する最適なソリューションを得ることができたhttps://github.com/cubiq/iscroll githubのドキュメントは素晴らしいですし、私はほとんどそれに続きました。これが私の実装の詳細です。

HTML: iScrollが使用できるいくつかのdivでコンテンツのスクロール可能な領域をラップしました:

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

CSS: 私は「タッチ」にModernizrクラスを使用して、スタイルの変更をタッチデバイスのみにターゲティングしました(タッチ時にインスタンス化されるのはiScrollのみであるため)。

.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: iScrollダウンロードからiscroll-probe.jsをインクルードしてから、以下のようにスクローラーを初期化しました。ここで、updatePositionは、新しいスクロール位置に反応する私の関数です。

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

現在の位置を取得するには、スクロールオフセットではなく、myScrollerを使用する必要があります。これは、http://markdalgleish.com/presentations/embracingtouch/から取得した関数です(非常に役立つ記事ですが、現在は少し古くなっています)。

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

他の唯一の問題は、スクロールしようとしていたページの一部が失われることがあり、スクロールを拒否することでした。#wrapperの内容を変更するたびにmyScroller.refresh()への呼び出しを追加する必要があり、それで問題が解決しました。

編集:もう1つの問題は、iScrollがすべての「クリック」イベントを食べることです。iScrollに「タップ」イベントを発生させ、「クリック」イベントではなくそれらを処理するオプションをオンにしました。ありがたいことに、スクロール領域をあまりクリックする必要がなかったので、これは大した問題ではありませんでした。


1

iOS 8が出たので、この問題はもうありません。スクロールイベントがiOS Safariでもスムーズに発生するようになりました。

したがって、scrollイベントハンドラーを登録してそのイベントハンドラーwindow.pageYOffset内をチェックすると、すべてが正常に機能します。


1
Cordovaの使用など、一部のユースケースではまだ存在します。developer.telerik.com/featured/...
diosney

6
私の経験では、これはまだ2019年に現在のiOSデバイスに問題が残っていることである
クリス・
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.