web-dev-qa-db-ja.com

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

IPadでスクロールイベントをキャプチャできないようです。これらの仕事のどれも、私が間違っていることは何ですか?

window.onscroll=myFunction;

document.onscroll=myFunction;

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

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

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

105
ck_

IPhoneOSはonscrollイベントをキャプチャしますが、予期しない方法を除きます。

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

同様に、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 も参照してください)

140
kennytm

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

古い投稿に別の回答を追加してすみませんが、通常、このコードを使用すると非常にうまくスクロールイベントを取得します(少なくとも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);
36
Dave Mackintosh

私は、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()にいくつかの呼び出しを追加する必要があり、問題を解決しました。

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

6

IOS 8がリリースされたため、この問題はもう存在しません。 iOS Safariでもscrollイベントがスムーズに起動されるようになりました。

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

1
Matthias Bohlen