9

「ホーム画面に追加」を使用して、Web アプリをネイティブ アプリのように感じさせたいとしましょう。最初の手順の 1 つは、デフォルトのスクロールを無効にすることです。簡単ですよね?

// window or document
window.addEventListener("touchmove", function(event) {
    // no more scrolling
    event.preventDefault();
}, false);

overflow-scrollingミックスに追加するまで、それはすべて問題なくダンディです。正確には、iOS では-webkit-overflow-scrolling: touch.

/* #scrollable happens to be a ul */
#scrollable {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

イベント防止を追加すると、コンテナー内のハードウェア アクセラレーションによるスクロールが機能しなくなり、意図した効果とは明らかに異なります。

明らかな解決策は次のようになります。

// you could do this for multiple elements, of course
var scrollable = document.querySelector("#scrollable");
scrollable.addEventListener("touchmove", function(event) {
    // no more bubbling :)
    event.stopPropagation();
}, false);

このソリューションでは問題が発生します。ただし、 で左または右にスクロールしようとする#scrollableと、デフォルトのスクロール リスナーに戻ります。明らかに、イベントを監視して、touchmoveイベントが左または右を追跡しているかどうかを確認する必要があります。残念ながら、コンテナー内で垂直方向にスクロールするときに、状況が完全に理解できない場合でも、デフォルトのスクロール リスナーに戻ります。

それで?さらに悪いことに、理想的にclickは、個々liの s (read: touchstart)でイベントを処理したり、クリックのようなイベントを処理したりできます。

var items = scrollable.querySelectorAll("#scrollable li");
for (var item = 0; item < items.length; item++) {
    items[item].addEventListener("touchstart", function() {
        // handle the touch start
    }, false);
}

この問題を解決するために、単純にclickイベントを使用することもできますが、デフォルトでは、タップと応答の間の遅延により、Web アプリケーションをネイティブに「感じさせる」という目標が設定されています。これを解決するために、 と のイベント リスナーを追加しtouchstartますtouchend

var items = scrollable.querySelectorAll("#scrollable li");
var activeItem = null, startTouch = null;
for (var item = 0; item < items.length; item++) {
    items[item].addEventListener("touchstart", function(event) {
        startTouch = event.touches[0];
        activeItem = this;
    }, false);
    items[item].addEventListener("touchend", function(event) {
        var touch = event.changedTouches[0];
        var deltaX = touch.pageX - startTouch.pageX
        var deltaY = touch.pageY - startTouch.pageY;
        // require the touchstart to be within 10 pixels of the touchend
        if (deltaX * deltaX + deltaY * deltaY <= 100)
            // handle "click" event
    }, false);
}

touchmoveこれで問題ありませんが、デフォルトのページ スクロールが一部のイベントを制御するという問題はまだ解決していません。何か案は?

4

1 に答える 1

8

window次のように、要素リスナーとscrollable要素リスナーのロジックを交換してみてください。

// window or document
window.addEventListener("touchmove", function(event) {
  if (!event.target.classList.contains('scrollable')) {
    // no more scrolling
    event.preventDefault();
  }
}, false);

// No special listeners needed on .scrollable elements

このようにして、スクロールできない要素をスクロールしようとしたときにのみデフォルトを防ぎます。

スクロール可能なコンテンツの上部/下部でドラッグを開始すると、アプリ全体が「バウンス」する可能性があるという問題がまだあります。この問題を修正するには、Joe Lambert の ScrollFixを参照してください。

于 2013-03-21T21:08:41.617 に答える