首頁  >  文章  >  web前端  >  詳解如何使用原生JS實現行動裝置web輪播圖效果

詳解如何使用原生JS實現行動裝置web輪播圖效果

巴扎黑
巴扎黑原創
2017-09-11 09:26:412532瀏覽

在做行動裝置開發的時候,必不可少的是輪播圖,以下這篇文章主要給大家介紹了關於利用純JS實現行動端web輪播圖的相關資料,重要的是結合Tween演算法造輪子,文中透過範例程式碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。

前言

相信大家應該都知道,行動端的輪播圖是我們比較常見的需求, 我們最快的實現方式往往是使用第三方的程式碼, 例如swiper , 但當遇到一些比較複雜的輪播圖需求時, 往往是束手無策,不知道怎麼改.      

#所以我們要嘗試去自己造一些輪子, 以適應各種複雜多變的需求;  另外一點, 自己寫的代碼如果有bug是很容易修復的, 對自身的提高也很大.

在沒有閱讀swiper源碼的過程下,我嘗試自己實現一個簡易而不失實用的移動端輪播圖, 經過幾個小時的思考和實踐終於還是實現了(如圖):


#實現行動端的輪播圖比pc複雜一些,主要表現在以下幾個方面:

     1.輪播圖要適應不同寬度/dpr的螢幕 

     2.需要使用touch相關的事件 

     3.不同機型對touch事件支援的不太一樣,可能會有一些相容性問題 

     4.手指移動圖片一部分距離,剩餘的距離需要自動完成 

     5.自動完成距離需要有ease 時間曲線 

##     5.自動完成距離需要有ease 時間曲線 


#但程式解決問題的想法都是差不多的,

我們在使用輪播圖的時候可以仔細觀察,透過現像看到本質:

  • 我們在使用輪播圖的時候可以仔細觀察,透過現像看到本質: 
  • 手指放圖片上, 手指向左或向右移動, 圖片也隨之移動; 
  • #手指移動的距離少時,圖片自動復原位置;手指移動的距離多時,自動切換到下一張; 
  • 手指向左或向右移動的快時,會切換到下一張; 
  • ##圖片輪播是無限循環的, 我們需要採用  3 1 2 3 1的方式來實現, 即N+2張圖來實現N張圖的無限循環輪播 

我們透過分析現象,可以提出一個基本實現方案:

     1. 手指觸摸事件可以透過touchstart touchmove touchend 3個事件來實現 

     2.在手指touchstart的時候我們需要記錄手指的x座標,  可以使用touch的pageX屬性; 還有這個時間點, 

##     3.手指下也需要記錄到手指的page ,並且記錄累計移動的距離moveX 


     4.手指離開的時候,記錄時間點, 根據前兩步驟計算的x方向移動的距離,時間點之差 


#     5.透過比較x方向移動距離來判斷移動方向, 以及是否應該切換到下一張圖; 根據時間判斷用戶是否進行了左右掃動的操作 


     6.移動圖片可以使用translate3d來實現,開啟硬體加速 


     7.移動一段距離需要easeOut效果,我們可以使用Tween演算法中的easeOut來實現我們每次移動的距離; 當然也可以使用js設定transition動畫 

實作原始碼(僅供參考):

head頭部樣式


<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>

touch事件部分


<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>

在觸控事件中最關鍵的參數是  pageX參數, 記錄x的位置.

當然這只是一個demo,還需要進一步的優化和封裝, 以便於我們用在真實的項目.


本demo只是提供了一個解決問題的思路, 有了這個思路,相信各種複雜的需求也得以解決...

以上是詳解如何使用原生JS實現行動裝置web輪播圖效果的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn