最近、2 画面のみの非常に小さな h5 アプリケーションを作成するタスクがありました。このアプリケーションでは、フルページを使用して水平方向の全画面スライド切り替えといくつかの簡単なアニメーション効果を実行する必要がありました。以前のこと。.jsとjqueryのパフォーマンスがあまり良くないので、それを実装するために自分で簡単なものを作りたいと思いました。最後に、zepto + Hammer.js と carousel を使用してこの問題を解決しました。その効果は非常に良好で、ページ全体で Gzip が有効になっていない場合、すべてのリソース リクエストのデータ サイズは約 200 KB でした。この記事では、このメソッドの実装アイデアを要約します。
効果のデモ (コードのダウンロード):
1) スライディング スクリーンはブートストラップのカルーセル プラグインを借用していますが、まったくありません。複雑です。カルーセルの実装アイデアから学ぶ必要があります。
2) スライド画面切り替えのトリガーは、通常、要素のクリック コールバックを通じてトリガーされます。スライド スクリーン ページの場合、ウィンドウの hashchange イベントを完全に使用して処理できるため、ハイパーリンクを通じてアンカー ポイントを設定するか、js を通じて location.hash を変更することで切り替えをトリガーできます。 ) モバイルがジェスチャー操作をサポートする必要があることを考慮すると、ジェスチャー ライブラリである Hammer.js の API は非常にシンプルで使いやすいです。
4) アニメーション効果には animate.css を使用できます。ただし、すべてのコードをコードに組み込む必要はありません。必要なアニメーション効果をコピーするだけで十分です。
5) jquery の代わりに、
6) スライディング スクリーン エフェクトはトランジション アニメーションを使用します。アニメーションの最後でコールバックに応答できるようにするには、transition.js を使用することを検討できます。これも Bootstrap によって提供されるツールですが、これは可能です。デフォルトでは jquery でのみ使用されます。zepto で使用するには少し変更する必要があります。
これらの重要なポイントは比較的大まかであり、後で詳しく紹介します。
2. HTML 構造
<div id="container" class="container"> <section id="page-1" class="page page--1"> </section> <section id="page-2" class="page page--2"> </section> <section id="page-3" class="page page--3"> </section></div>
html,body { height: 100%; -webkit-tap-highlight-color: transparent;}.container,.page { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden;}.page { overflow: hidden; display: none; -webkit-transition: -webkit-transform .4s ease; transition: transform .4s ease; -webkit-backface-visibility: hidden; backface-visibility: hidden;}
デモ ページの HTML 構造は次のとおりです。
デモ関連の CSS は表示されません。このうちアニメーション化にはgithubで公開されているアニメーションライブラリであるanimate.cssを適用する必要があります。
<div id="container" class="container"> <section id="page-1" class="page page--1"> <div class="page__jump"><a href="#page-2" title="">下一页</a></div> <p class="page__num animated">1</p> </section> <section id="page-2" class="page page--2"> <div class="page__jump"><a href="#page-1" title="">上一页</a><a href="#page-3" title="">下一页</a></div> <p class="page__num animated">2</p> </section> <section id="page-3" class="page page--3"> <div class="page__jump"><a href="#page-2" title="">上一页</a></div> <p class="page__num animated">3</p> </section></div>
3. スライド画面切り替えの実装のアイデア
.page--active は、現在表示されているページを示します。 ページが初期化されたら、次の JS 呼び出しを使用して .page-active:
.page.page--active,.page.page--prev,.page.page--next { display: block;}.page.page--next,.page.page--active.page--active-right { -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0);}.page.page--prev,.page.page--active.page--active-left { -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0);}.page.page--next.page--next-left,.page.page--prev.page--prev-right,.page.page--active { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);}
を最初のページに追加します。ページはデフォルトで最初のページに表示されます。これらの CSS の使用原則は、画面を左にスライドすることで説明されています。
var $activePage;//初始化显示第一页(function () { $activePage = $('#page-1'); $activePage.addClass('page--active');})();
2 番目のステップは、現在のページのセクションを見つけて、それに page--active-left を追加することです。このクラスは、translate3D 属性の値を変更します。現在のページが 1 画面左にスライドします。
このクラスは、translate3D の値を変更するため、2 番目のステップと同時に、次のページのセクションに page--next-left を追加します。属性を指定すると、次のページが 1 画面左にスライドします。
3 番目のステップは、現在のページと次のページのスライド アニメーションが終了した後、元の現在のページを見つけてそのページを削除します。 page--active-left クラス;
3 番目のステップでは、同時に次のページを見つけて、page--next クラスと page--next-left クラスを削除し、page--active を追加します。
GIF の説明は次のとおりです:
最初のステップは、次のセクションを見つけることです。前のページを作成し、page- -prev クラスを追加し、現在のページの左側に配置して、画面をスライドする準備をします。
2 番目のステップと同時に、page--prev- を追加します。前のページのセクションに右に移動します。このクラスは、translate3D 属性値を変更するため、前のページは 1 画面右にスライドします。
現在のページのスライド アニメーションの後の 3 番目のステップ。前のページが終了し、元の現在のページを見つけて、page--active クラスと page--active-right クラスを削除します。
3 番目のステップと同時に、前のページを見つけて、page--prev を削除します。そして page--prev-right クラスを追加し、page--active を追加します。
上記の実装原則に基づいて、次のように JS 関数にカプセル化されます。
ページの初期化時にデフォルトで $activePage が最初のページとして指定されるため、各スライドが最新の現在のページになると更新されるため、呼び出すときは対象のページの ID をスライド関数に渡すだけです。上記のコードについては次のような疑問があるかもしれません:
var TRANSITION_DURATION = 400, sliding = false; function getSlideType($targetPage) { var activePageId = $activePage.attr('id'), targetPageId = $targetPage.attr('id'); return activePageId < targetPageId ? 'next' : activePageId == targetPageId ? '' : 'prev';}function slide(targetPageId) { var $targetPage = $('#' + targetPageId); if (!$targetPage.length || sliding) return; var slideType = getSlideType($targetPage), direction = slideType == 'next' ? 'left' : 'right'; if (slideType == '') return; sliding = true; $targetPage.addClass('page--' + slideType); $targetPage[0].offsetWidth; $activePage.addClass('page--active-' + direction); $targetPage.addClass('page--' + slideType + '-' + direction); $activePage .one($.transitionEnd.end, function () { $targetPage.removeClass(['page--' + slideType, 'page--' + slideType + '-' + direction].join(' ')).addClass('page--active'); $activePage.removeClass(['page--active', 'page--active-' + direction].join(' ')); $activePage = $targetPage; sliding = false; }) .emulateTransitionEnd(TRANSITION_DURATION);}
2) $.transitionEnd.end と EmulateTransitionEnd の関数については、次のセクションで説明します。
bootstrap提供了一个工具,transition.js,用来判断浏览器是否支持css动画回调事件,以及在浏览器没有在动画结束后自动触发回调的特殊情况下通过模拟的方式来手动触发回调,原先这个工具只能配合jquery使用,为了在zepto中使用,必须稍微改变一下,下面就是改变之后的代码:
(function(){ var transition = $.transitionEnd = { end: (function () { var el = document.createElement('transitionEnd'), transEndEventNames = { WebkitTransition: 'webkitTransitionEnd', MozTransition: 'transitionend', OTransition: 'oTransitionEnd otransitionend', transition: 'transitionend' }; for (var name in transEndEventNames) { if (el.style[name] !== undefined) { return transEndEventNames[name]; } } return false; })() }; $.fn.emulateTransitionEnd = function (duration) { var called = false, _this = this, callback = function () { if (!called) $(_this).trigger(transition.end); }; $(this).one(transition.end, function () { called = true; }); setTimeout(callback, duration); return this; };})();
$.transitionEnd.end表示当前浏览器支持的动画结束事件的名称。$.fn.emulateTransitionEnd是一个扩展了Zepto原型的一个方法,传入一个动画的过渡时间,当这个时间段过完之后,如果浏览器没有自动触发回调事件,called就始终是false,setTimeout会导致callback被调用,然后callback内部就会手动触发动画结束的回调。为什么要通过这个方式来模拟动画结束,是因为浏览器即使支持动画结束事件的回调,但是有些时候并不会触发这个事件,或者在动画结束后不能立即触发,影响回调的准确性。传入的duration应该与执行动画的元素,在css上设置的transtion-duration相同,注意以下代码中标黄的部分:
var TRANSITION_DURATION = 400;$activePage .one($.transitionEnd.end, function () { $targetPage.removeClass(['page--' + slideType, 'page--' + slideType + '-' + direction].join(' ')).addClass('page--active'); $activePage.removeClass(['page--active', 'page--active-' + direction].join(' ')); $activePage = $targetPage; sliding = false; }) .emulateTransitionEnd(TRANSITION_DURATION);
.page { overflow: hidden; display: none; -webkit-transition: -webkit-transform .4s ease; transition: transform .4s ease; -webkit-backface-visibility: hidden; backface-visibility: hidden;}
PC端滑屏都是给元素添加点击事件触发的,移动端可以利用window的hashchange事件:
$(window).on('hashchange', function (e) { var hash = location.hash; if (!hash) hash = '#page-1'; slide(hash.substring(1));});location.hash = '#page-1';
hashchange事件,在js代码中通过改变loaction.hash或者是点击 < a href ="#page-2" title ="" > 下一页 a > 这样的超链接时,都会触发,所以只要在这个事件的回调去做滑屏切换即可。这样那些上一页和下一页的链接元素都不用加事件了。
hammer.js是一个手势库,支持常用的手势操作,使用简单,引入它的js之后,通过以下的方式来支持手势滑屏:
//初始化手势滑动var container = document.getElementById('container'), mc = new Hammer.Manager(container), Swipe = new Hammer.Swipe();mc.add(Swipe);mc.on('swipeleft', function (e) { swipteTo('next', e);});mc.on('swiperight', function (e) { swipteTo('prev', e);});function swipteTo(slideType, e) { var $targetPage = $activePage[slideType]('.page'); $targetPage.length && (location.hash = '#' + $targetPage.attr('id'));}
把整个container元素作为滑屏的stage,监听到swipeleft事件,就表示向左滑,页面应该显示下一页;监听到swiperight事件,就表示向右滑,页面应该显示下一页。
animate.css的使用就不详细介绍了,比较简单,这是它的github地址: https://github.com/daneden/animate.css ,是一个非常好用的动画库。本文把最近的一点工作经验记录了下来,技术上的东西,有的时候一些文字不能完全讲的清楚,所以我只能尽自己的能力去把一些问题讲地稍微细致一点,说的不对和有问题的尽管在评论区与我说明,我会认真查看,另外我自己对移动端这一块入门不深,您有更好的见解,欢迎与我们一起分享。谢谢您的阅读,马上就新年,祝您猴年大吉!
本文源码下载