ホームページ  >  記事  >  ウェブフロントエンド  >  ネイティブ JS を使用してモバイル Web カルーセル効果を実現する方法の詳細な説明

ネイティブ JS を使用してモバイル Web カルーセル効果を実現する方法の詳細な説明

巴扎黑
巴扎黑オリジナル
2017-09-11 09:26:412527ブラウズ

モバイル開発を行う場合、カルーセルグラフィックスは不可欠です。次の記事では、純粋なJSを使用してモバイルWebカルーセルグラフィックスを実現するための関連情報を主に紹介します。重要なのは、ホイールを作成するためにTweenアルゴリズムを組み合わせることです。サンプルコードを通じて詳しく説明します。必要な場合は、一緒に見てみましょう。

前書き

モバイル端末上のカルーセル画像は私たちのより一般的なニーズであることを誰もが知っておくべきだと思いますが、それらを実装する最速の方法は、多くの場合、スワイパーなどのサードパーティのコードを使用することですが、いくつかの比較に遭遇した場合。複雑なカルーセルが必要な場合、多くの場合、それを変更する方法がわかりません。そのため、さまざまな複雑で変化するニーズに適応するために、いくつかのホイールを自分で作成する必要があります。ポイントは、私たちが書いたコードにバグがある場合、修復するのが非常に簡単で、コード自体が大幅に改善されたということです

数時間の作業の後、スワイパーのソース コードを読まずに、シンプルで実用的なモバイル カルーセル チャートを自分で実装してみました。思考と実践 最終的にそれが実現されました (図に示すように):


モバイルでのカルーセル画像の実装は、主に次の点で PC よりも複雑です:

1. カルーセル画像さまざまな状況に適応する必要があります 幅/奥行き画面

2. タッチ関連のイベントを使用する必要があります

3. モデルごとにタッチイベントのサポートが異なり、互換性の問題が発生する可能性があります

4.画像の距離の一部を指でなぞり、残りの距離は自動的に完了する必要があります

5. 距離を自動的に完了するにはイーズタイムカーブが必要です

しかし、プログラミングの問題を解決するためのアイデアは似ています、


カルーセル チャートを使用すると、注意深く観察でき、現象を通して本質を見ることができます:


カルーセル チャートを使用すると、注意深く観察し、現象を通して本質を見ることができます:
  • 指を置く画像上で指を左または右に動かすと、それに応じて画像も移動します
  • 指が短い距離を移動すると、画像は自動的に元の位置に戻ります。次の画像に切り替えます
  • 指を左右に速く動かすと、画像は自動的に元の位置に戻ります
  • 画像カルーセルは無限ループです。それを達成するには 3 1 2 3 1 メソッドを使用する必要があります。つまり、N 枚のピクチャの無限ループ カルーセルを達成するには N+2 枚のピクチャが必要です
現象を分析することで、基本的な実装計画を提案できます:

1. 指タッチイベントは、touchstart、touchmove、touchend の 3 つのイベントを通じて実現できます。

2. 開始 x 座標をタッチするときに指を記録する必要があり、今回は touch の pageX 属性を使用できます。ポイント、

3. 指が移動するとき、最初の 2 つのステップで計算された x 方向の移動距離、時点の差に基づいて、ページ ポイントを記録する必要もあります

5. の方向を決定します。 x方向に移動した距離を比較して次の画像に切り替えるかどうかを判断する; 時間に基づいてユーザーが進むかどうかを判断する 左右にスワイプする操作

6. 移動画像はtranslate3dとを使用して実現できます。ハードウェア アクセラレーションをオンにする

7. 一定の距離を移動するには、easeOut エフェクトを使用して、毎回の移動距離を認識できます。 もちろん、js を使用してトランジション アニメーションを設定することもできます。


実装ソースコード(参考のみ):

head style

<head> 
 <meta charset="UTF-8"> 
 <meta name="viewport" content="width=device-width,initial-scale=.5,maximum-scale=.5"> 
 <title>移动端轮播图</title> 
 <style> 
 * { 
 box-sizing: border-box; 
 margin: 0; 
 padding: 0 
 } 
 .banner { 
 overflow: hidden; 
 width: 100%; 
 height: 300px 
 } 
 .banner .img-wrap { 
 position: relative; 
 height: 100% 
 } 
 .banner img { 
 display: block; 
 position: absolute; 
 top: 0; 
 width: 100%; 
 height: 100% 
 } 
 </style> 
</head>

HTML構造


<p class="banner"> 
 <p class="img-wrap" id="imgWrap"> 
 <img src="images/banner_3.jpg" data-index="-1"> 
 <img src="images/banner_1.jpg" data-index="0"> 
 <img src="images/banner_2.jpg" data-index="1"> 
 <img src="images/banner_3.jpg" data-index="2"> 
 <img src="images/banner_1.jpg" data-index="3"> 
 </p> 
</p>
JS コード 1、easeOut アニメーションの動き、

ここで、HTMLElement.prototype.tweenTranslateXAnimate は、すべての HTML 要素クラスに拡張された tweenTranslateXAnimate メソッドです

一定の距離を移動するには、この反復的な操作を完了するためにタイマーを使用する必要があります


<script> 
 HTMLElement.prototype.tweenTranslateXAnimate = function (start, end, callback) { 
 var duration = 50; 
 var t = 0; 
 var vv = end - start; 
 var Tween = { 
 Quad: { 
 easeOut: function (t, b, c, d) { 
  return -c * (t /= d) * (t - 2) + b; 
 } 
 } 
 }; 
 
 this.timer = setInterval(function () { 
 var dis = start + Tween.Quad.easeOut(++t, 0, vv, duration); 
 this.style.transform = &#39;translate3d(&#39; + dis + &#39;px, 0, 0)&#39;; 
 if (vv > 0 && parseInt(this.style.transform.slice(12)) >= end) { 
 this.style.transform = &#39;translate3d(&#39; + parseInt(dis) + &#39;px, 0, 0)&#39;; 
 clearInterval(this.timer); 
 callback && callback(); 
 } 
 if (vv < 0 && parseInt(this.style.transform.slice(12)) <= end) { 
 this.style.transform = &#39;translate3d(&#39; + parseInt(dis) + &#39;px, 0, 0)&#39;; 
 clearInterval(this.timer); 
 callback && callback(); 
 } 
 }.bind(this), 4); 
 } 
</script>


タッチイベント部分


<script> 
 ~function () { 
 var lastPX = 0; // 上一次触摸的位置x坐标, 需要计算出手指每次移动的一点点距离 
 var movex = 0; // 记录手指move的x方向值 
 var imgWrap = document.getElementById(&#39;imgWrap&#39;); 
 var startX = 0; // 开始触摸时手指所在x坐标 
 var endX = 0; // 触摸结束时手指所在的x坐标位置 
 var imgSize = imgWrap.children.length - 2; // 图片个数 
 var t1 = 0; // 记录开始触摸的时刻 
 var t2 = 0; // 记录结束触摸的时刻 
 var width = window.innerWidth; // 当前窗口宽度 
 var nodeList = document.querySelectorAll(&#39;#imgWrap img&#39;); // 所有轮播图节点数组 NodeList 
 
 // 给图片设置合适的left值, 注意 querySelectorAll返回 NodeList, 具有 forEach方法 
 nodeList.forEach(function (node, index) { 
 node.style.left = (index - 1) * width + &#39;px&#39;; 
 }); 
 
 /** 
 * 移动图片到当前的 tIndex索引所在位置 
 * @param {number} tIndex 要显示的图片的索引 
 * */ 
 function toIndex(tIndex) { 
 var dis = -(tIndex * width); 
 var start = parseInt(imgWrap.style.transform.slice(12)); 
 // 动画移动 
 imgWrap.tweenTranslateXAnimate(start, dis, function () { 
 setTimeout(function () { 
  movex = dis; 
  if (tIndex === imgSize) { 
  imgWrap.style.transform = &#39;translate3d(0, 0, 0)&#39;; 
  movex = 0; 
  } 
  if (tIndex === -1) { 
  imgWrap.style.transform = &#39;translate3d(&#39; + width * (1 - imgSize) + &#39;px, 0, 0)&#39;; 
  movex = -width * (imgSize - 1); 
  } 
 }, 0); 
 }); 
 } 
 
 /** 
 * 处理各种触摸事件 ,包括 touchstart, touchend, touchmove, touchcancel 
 * @param {Event} evt 回调函数中系统传回的 js 事件对象 
 * */ 
 function touch(evt) { 
 var touch = evt.targetTouches[0]; 
 var tar = evt.target; 
 var index = parseInt(tar.getAttribute(&#39;data-index&#39;)); 
 if (evt.type === &#39;touchmove&#39;) { 
 var di = parseInt(touch.pageX - lastPX); 
 endX = touch.pageX; 
 movex += di; 
 imgWrap.style.webkitTransform = &#39;translate3d(&#39; + movex + &#39;px, 0, 0)&#39;; 
 lastPX = touch.pageX; 
 } 
 if (evt.type === &#39;touchend&#39;) { 
 var minus = endX - startX; 
 t2 = new Date().getTime() - t1; 
 if (Math.abs(minus) > 0) { // 有拖动操作 
  if (Math.abs(minus) < width * 0.4 && t2 > 500) { // 拖动距离不够,返回! 
  toIndex(index); 
  } else { // 超过一半,看方向 
  console.log(minus); 
  if (Math.abs(minus) < 20) { 
  console.log(&#39;距离很短&#39; + minus); 
  toIndex(index); 
  return; 
  } 
  if (minus < 0) { // endX < startX,向左滑动,是下一张 
  toIndex(index + 1) 
  } else { // endX > startX ,向右滑动, 是上一张 
  toIndex(index - 1) 
  } 
  } 
 } else { //没有拖动操作 
 
 } 
 } 
 if (evt.type === &#39;touchstart&#39;) { 
 lastPX = touch.pageX; 
 startX = lastPX; 
 endX = startX; 
 t1 = new Date().getTime(); 
 } 
 return false; 
 } 
 
 imgWrap.addEventListener(&#39;touchstart&#39;, touch, false); 
 imgWrap.addEventListener(&#39;touchmove&#39;, touch, false); 
 imgWrap.addEventListener(&#39;touchend&#39;, touch, false); 
 imgWrap.addEventListener(&#39;touchcancel&#39;, touch, false); 
 
 }(); 
 
</script>
touch イベントで最も重要なパラメータは、x の位置を記録する pageX パラメータです。

もちろん、これは単なるデモであり、これを使用できるようにさらに最適化とカプセル化が必要です。実際のプロジェクト


このデモは、問題を解決するためのアイデアを提供するだけです。このアイデアがあれば、さまざまな複雑なニーズも解決できると思います...

以上がネイティブ JS を使用してモバイル Web カルーセル効果を実現する方法の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。