最近、会社の株取引コンテストのページの作成に忙しく、昨日ようやくオンラインに公開しました。一見シンプルなページですが、作ってみて初めて苦労や隠れた落とし穴に気づきます。 jquery はページ ロジックの記述に直接使用されるため、想像よりもはるかに複雑です。レイアウト、機能、ロジックのいずれの観点においても、要約する価値があるものがあります。
クリックして昨日立ち上げたページを表示します
この記事では主にシームレススクロールの実装について説明します。
私が初めて js を学び始めたとき、シームレスなスクロールは魔法の機能だと本当に感じました。舞台裏で何が起こっているのでしょうか?ブロックの数が少ないのになぜ転がらないのでしょうか?その後、原理を理解した後、それはいくつかの盲目的な方法によって達成されることがわかりました。
シームレスにスクロールする必要がある 4 つの要素が、1 つの ul.item 内の 6 li.item であると仮定します。コンテナ .wrap 内の ul.items のスクロールを制御します。 HTML コードは次のとおりです。
ul.items は、className が items である ul 要素を表し、他の場所でも同じことが当てはまります
<div class="wrap"> <ul class="items"><!-- --><li class="item"><img src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner0.8a07a886.jpg" alt=""></li><!-- --><li class="item"><img src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner1.56bcecb3.png" alt=""></li><!-- --><li class="item"><img src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner2.9a7e8842.jpg" alt=""></li><!-- --><li class="item"><img src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner3.47acdfbd.png" alt=""></li><!-- --><li class="item"><img src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner5.e9205d49.jpg" alt=""></li><!-- --><li class="item"><img src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner6.83b14a71.png" alt=""></li><!-- --></ul></div>
私たちの目標は、次のとおりです。水平スクロールなので li.item を水平に配置する必要があります。目標を達成するために一般的に使用される方法は、float: left を使用するか、display: inline-block を使用することです。ページ要素の動きを制御することは、要素の left、top、translateX、translateY を制御すること以外の何ものでもありません。もう 1 つは、スクロール距離 (scrollTop、scrollLeft) を制御することです。レイアウトの選択は、js コントロール属性の選択にも影響します。
この例では、display: inline-block レイアウトを使用することを選択し、ul.items のscrollLeft 値を制御して ul 全体をスクロールします。レイアウトでは次の点に注意する必要があります。
ここでの非表示は ul.items との違いに注意してください。 float: 左のレイアウト。
.items { overflow: hidden; }
ul.itemsの内容はラップできないため、
.items { white-space: nowrap; }
をモバイル端末に合わせる必要がありますが、構成幅が小さくなると必然的にアイテムの幅も小さくなります。
@media (max-width: 780px) { .item { width: 190px; }}@media (max-width: 580px) { .item { width: 160px; }}
HTML レイアウトの は、display: inline-block 要素間のギャップをなくすためのものです。
では、シームレスなスクロールを実現する盲目的なトリックとは何でしょうか?本来なら絵で説明したほうがわかりやすいのですが、ここではぐずぐずして言葉で説明し、理解していただければと思います。
子要素 123456 があります。1 つずつ左にスクロールしてコピーすると、123456123456 になります。ボディ全体を 2 番目の 1 に移動すると、全体の位置が最初の 1 に戻ります。これは div.items の overflow: hidden のため、で発生した変更を使用できません。真ん中 肉眼で認識すると左に動き続けて止まらないように感じます。
理解できない場合は、コードで理解するか、メッセージを残してください。
スポーツに関して言えば、setTimeout または setInterval を使用する方法がよく思い浮かびますが、html5 ではより高性能なメソッド requestAnimationFrame が提供されます。
パフォーマンスの点では、requestAnimationFrame > setTimeout > setInterval。具体的な理由を知るために関連情報を見つけることができます。 setTimeout の最小タイミング値は 100/60 です。したがって、パフォーマンスと互換性の観点から、モーションを実装するときは、次のステートメントを作成することがよくあります:
var lastTime = 0, nextFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { var currTime = + new Date, delay = Math.max(1000/60, 1000/60 - (currTime - lastTime)); lastTime = currTime + delay; return setTimeout(callback, delay); }, cancelFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame || clearTimeout;
どこにスクロールするかを知る必要があります。 0 に戻ると、この位置はコピー前のすべてのサブ要素の合計の長さになります。ただし、デバイスの幅の変更により子要素の幅も変更されるため、レイアウトを一致させるには、次の操作を行う必要があります。
// 单个子元素的宽度var itemW = 240;if ($items.children().eq(0).width() == 190) { itemW = 190;}if ($items.children().eq(0).width() == 160) { itemW = 160;}// 目标位置var target = itemW * $items.children().length;
ブラインドネスを実現するには、子要素のコピー
$items.html( $items.html() + $items.html() );
モーション関数を定義します。ここでのモーションは均一モーションなので、+1 を維持するだけで済みます。より速く移動する必要がある場合は、シームレスなスクロールが実現されるように、
var timer = null;function adAni() { timer = nextFrame(function() { scrollX += 1; // 当递增到大于了目标距离,就直接变为0 if (scrollX >= target) { scrollX = 0; } $items.scrollLeft(scrollX); adAni(); });}// 运行这个函数就可以实现无缝滚动啦。adAni();
をもう少し追加します。しかし、他にもいくつかのニーズがあります。たとえば、マウスオーバーが発生した場合、スクロールを停止し、マウスオーバーを離れた後にスクロールを再開する必要があります。ニーズの変化により、モバイル端末上で items.ul をスライドさせ、指を離した後もスクロールを継続できることも必要です。そのため、PCとモバイルを区別する機能が必要になります。 UAの違いによって区別されます。
function isMobile() { return /(iphone|ipad|ipod|ios|android|mobile|blackberry|iemobile|mqqbrowser|juc|fennec|wosbrowser|browserng|Webos|symbian|windows phone)/i.test(navigator.userAgent);}
PC側ではマウスを近づけると停止し、マウスを離すとスクロールを続けます
if (!isMobile()) { $items.on('mouseover', function() { cancelFrame(timer); }).on('mouseout', function() { adAni(); });}
モバイル側では左にスライドできます。と右にスライドすると自動スクロールを停止し、放した後も自動スクロールを続けます。モバイル側のスライディング イベントは、主に touchstart、touchmove、および touchend によって実装されます。これらは、PC 側の Mousedown、mousemove、mouseup と同様です。
var sX, sL;$items.on('touchstart', function(e) { cancelFrame(timer); sX = e.originalEvent.changedTouches[0].pageX; sL = $items.scrollLeft();}).on('touchmove', function(e) { var dis = e.originalEvent.changedTouches[0].pageX - sX; var nowX = sL - dis; if (nowX > target) { nowX = 0; } $items.scrollLeft(nowX);}).on('touchend', function(e) { scrollX = $items.scrollLeft(); if (scrollX >= target) { scrollX = 0; } adAni();})
これで基本的には完了です。これは比較的単純な例ですが、requestAnimationFrame を使用してモーションを実装したり、モバイル端末上でイベントをスライドさせたりするなど、一般的に使用される関数もいくつか含まれています。ここにまとめて共有させていただきますので、ご質問がございましたらお気軽にご相談ください。
segmentfault の記事は codepen のデモをサポートしていないため、記事の冒頭にあるリンクにアクセスして表示するか、私の個人ブログにアクセスして元のブログのテキストを表示することができます。
ご質問がございましたら、公式アカウントにメッセージを残してください。WeChat で isreact を検索すると見つかります^_^。