0

これは奇妙なものです!

概要:
私はWebアプリを作成しており、Facebookアプリにあるものと同様のメニューを作成しました。右にスワイプすると表示され、左にスワイプすると非表示になります。

これを行うには、タッチスタートイベントをページの本文にバインドます。この時点で、指を押す開始ポイントを記録し、タッチムーブイベントとタッチエンドイベントもバインドします。touch moveイベントは、現在の指の位置を検出し、translate3d(x、y、z)を指の位置​​に一致するように設定することにより、ページコンテンツを含むdivを移動します。

それは実際に本当に素晴らしい働きをします。

次に、タッチエンドで、指がメニューの表示をトリガーするのに十分な距離まで移動したのか、コンテンツが元の位置に戻るのに十分な距離に移動したのかを調べます。選択に関係なく、コンテンツdivに-webkit-transition:-webkit-transformなどを適用するクラスを適用します。次に、もう一度translate3d(x、y、z)を使用して、決定された終了位置を設定し、それ以上のタップが一時的に機能しないようにする変数も設定します。

そして、これは問題があるところです!

問題:
この時点で、コンテンツが基本構造、つまり記事のレイアウトページで単純な場合、移行は迅速かつ瞬時に行われます。でも!コンテンツが複雑な場合、つまりデータのテーブルが大きい場合は、1〜30秒の範囲で一時停止が発生します...非常にイライラします。

最終的に機能する場合、コールバックは本体からtouchmoveイベントとtouchendイベントのバインドを解除し、タップを停止する変数が設定解除され、再開する準備が整います。

私はiPad1でテストしています。スワイプの速度と一時停止の長さの間に相関関係はないようです。また、コンテンツが移動するために残された距離の間に何もありません。

最後に、これが鍵だと思います!
同じ開閉アクションを自動的に実行するボタンがあり(これもFacebookのように)、正常に機能します。スワイプすると一時停止し、そのボタンをタップすると、ベースが切り替わるときに間違った方向ではありますが、すぐに機能し始めます。すでに開くように設定されている変数。ある種のアニメーションキューをクリアして、それ自体を整理するようなものです...

いくつかのコード:
javascript

$body.bind({
    'touchstart': function(e){

        if( !swipeBan ){

            // Reset
            var used = false,
                triggered = false,
                dir = false;

            // Get start point
            start.x = e.originalEvent.touches[0].pageX;
            start.y = e.originalEvent.touches[0].pageY;

            $body.bind({
                'touchmove':    function(e){

                    // Get current value (will be the end value too)
                    end.x = e.originalEvent.touches[0].pageX;
                    end.y = e.originalEvent.touches[0].pageY;

                    // If we have not chosen a direction, choose one
                    if( !dir ){

                        dir = getDir();

                    }else{

                        var left = open && dir == 'left',
                            right = !open && dir == 'right';

                        if( left || right ){

                            var x = left ? maxSwipe - getDist('left') : getDist('right');

                            $content.setTransform(x);

                            used = true;
                            triggered = left ? maxSwipe - x > swipeTrigger : x > swipeTrigger;

                            e.preventDefault();

                        }

                    }

                },
                'touchend': function(e){

                    // Only go further if we are going the correct direction
                    if( used ){

                        swipeBan = true;

                        // Get ready for animation
                        function done(){

                            // Get touching!
                            swipeBan = false;

                            // Stop animating
                            $content.removeClass('animate');

                        }

                        // Add animate class
                        $content.addClass('animate');

                        // Set the value
                        if( ( !open && triggered ) || ( open && !triggered ) ){

                            $content.setTransform(maxSwipe,0,function(){
                                done();
                            });

                            $body.removeClass('closed');

                            open = true;

                        }else if( ( !open && !triggered ) || ( open && triggered ) ){

                            $content.setTransform(0,0,function(){
                                done();
                            });

                            $body.addClass('closed');

                            open = false;

                        }

                    }

                    // Unbind everything
                    $body.unbind('touchmove touchend');

                }
            });

        }else{

            e.preventDefault();

        }

    }
});

上で使用したsettransformプラグイン。

$.fn.setTransform = function(x,y,callback){

    y = y ? y : '0';

    var $this = $(this);

    if( callback ){

        $this.one('webkitTransitionEnd',function(){

             callback.apply(this);

        });

    }

    $this.css({
        '-webkit-transform':    'translate3d(' + x + 'px,' + y + '%,0)'
    });

    return this;

}

CSS、非常にシンプル。適用される他のスタイルもありますが、それらは純粋に視覚的なものです。

#content.animate {
    -webkit-transition: -webkit-transform .3s cubic-bezier(.16,0,0,1);
}

長い投稿で申し訳ありませんが、これは私をたくさん悩ませてきました!問題を分類できない場合は、それを取り除かなければならない時点です。

誰かがこれを以前に見たことがあり、助けてくれることを願っています。(または、上記のコードで明らかに明らかなエラーを確認できます!)

ありがとう、

意思 :)

4

1 に答える 1

0

私はこれを最終的に解決しました、それが他の人に役立つかもしれないと思いました!

touchmoveトランジションの終了から、移動を完了するトランジションの開始までの間は、ページにクラスを追加しないでください。

私のプロセスは以前は次のとおりでした。

  1. タッチスタート時に指xを取得
  2. 現在位置と開始位置に基づくタッチ移動位置要素について
  3. タッチエンドで、移動距離に基づいてアニメーションを続行するか反転するかを決定します。
  4. 最終的な位置を決定する親要素にcloseまたはopenのクラスを追加します。

ただし、このクラスを追加すると、サファリはスタイルの変更を強制的に適用します。これは、変更がほとんどないか、まったくない場合でも、明らかに非常に集中的です。これが一時停止の理由です。

クラスを追加する代わりにjavascriptを使用して遷移を適用するようにプロセスを変更しましたが、これでスムーズになりました。

于 2012-04-27T14:54:06.857 に答える