一個月前仍是用vue作微信H5,後面公司業務發展,入坑小程序,作了幾款小程,跑了很多坑, 也會陸續在後面幾節跟你們分享。 在這節給你們分享這個 小程序圖片輪播實現方案
能看到 左右兩邊若是有圖,會顯示一部分出來,原本也想用 小程序自帶的swiper 組件,沒法達到,左右兩邊 看到上(下)圖片的效果,沒法改變他組件原來的設置(坑)vue
在開始以前,先想一想h5是怎麼實現的,用原生寫,能夠在某個固定框的盒子裏,再用一個div 包住 x 張圖,而後改變 ontouchmove 時改變 left(或者translateX) ,判斷用戶手指滑動足夠距離,就滑到下(上)一張,
最後判斷到最後一張或者第一張,不滑動就好(在這裏不作無縫滾動)。
jquery,vue 不少庫都可以實現jquery
咱們只要 實現了第一張圖的滑動,記錄這個偏移量 tranX1 = 0 + offsetX, 第二張的滑動距離 tranX2 = tranX1 + offsetX ,第三張的滑動距離 tranX3 = tranX2 + offsetX ... 相反方向 也就 遞減 tranX1 = tranX2 - offsetX ... 而後判斷臨界值就OK了 瞭解了大概的滑動過程如今就能夠掀起袖子幹了~
寫了個 swiper 的方法,用原形鏈繼承的方式,與小程序的page({})裏面代碼儘可能分開, 用慣了Vue的雙向綁定,特別討厭小程序的 this.setData 並且是異步的(坑),this有時候要用變量保留,
先定義了幾個變量,初始化一些必要參數,
記錄 touch 過程當中 滑動開始的座標,滑動過程當中,和滑動結束時的座標,git
'use strict'; var swiper = function(opt){ // 保存設置 this.opt =opt // 當前 移動塊停留索引 this.swiperIndex = 0 // 盒子容器總偏移量 this.boxTranslateX = 0 // 每移動一張圖會增長的偏移量 this.singleOffsetX = -610 // 觸摸 this._x_start = 0 this._y_start = 0 // 移動 this._x_move = 0 // 離開 this._x_end = 0 // 偏移量 this._x_offset = 0 // move 過程當中真實偏移 this._x_realOffset = 0 this.screenWidth = 750 this.screenHeight = 1210 this.pixelRatio = 2 // rpx this.maxTranX = this.singleOffsetX * (this.opt.imgLength -1 ) // 容器寬度 width 100 是兩邊靠牆 this.width = 100 * 2 + (this.opt.imgLength - 1) *60 + 550 * this.opt.imgLength // 計算寬轉換比例 this.computedScreenRatio(opt.systemInfo) }
上,屏幕寬度爲375px,共有750個物理像素,則750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。算法
// 計算寬轉換比例 swiper.prototype.computedScreenRatio = function (systemInfo){ this.pixelRatio = systemInfo.pixelRatio this.screenWidth = systemInfo.screenWidth this.screenHeight = systemInfo.screenHeight //this.singleOffsetX = -610 // 奇怪的i5 按照算法會 多偏移2 px if (systemInfo.model.indexOf('iPhone 5') > -1 ){ this.singleOffsetX = -(610 * (this.screenWidth / 750) -2 ).toFixed() } else{ this.singleOffsetX = -610 * (this.screenWidth / 750) } this.maxTranX = this.singleOffsetX * (this.opt.imgLength - 1) // 回調綁定vm ,渲染盒子寬度 this.opt.success && this.opt.success(this.width) }
計算最後手指離開的座標,_x_realOffset用來保存計算 真實的在x方向上的距離R小程序
// bindtouchstart swiper.prototype.keepStartX = function(e, callback){ this._x_start = e.touches[0].pageX this._y_start = e.touches[0].pageY callback && callback() } // bindtouchmove /* 函數說明 moveBox @params e 事件 @params {function} callback 圖片盒子的偏移量改變,綁定到vm 上面,視圖發生變化 */ swiper.prototype.moveBox = function (e, callback) { this._x_move = e.touches[0].pageX this._x_offset = this._x_move - this._x_start var lastTranX = this.computedTranX(this._x_offset) this._x_realOffset = lastTranX callback && callback(lastTranX) } /* 函數說明 根劇移動偏移量臨界值計算出真實位移用 滑下一張 判斷是否超出臨界值,超出則等於臨界值 若不超過則偏移量 = 手指(touch)移動距離 + 當前盒子偏移量 */ swiper.prototype.computedTranX = function ( offsetX ){ // 滑向上一張 if( offsetX > 0 ){ return offsetX + this.boxTranslateX } // 滑動下一張 else if (offsetX < 0 ){ if ( Math.abs(offsetX - this.boxTranslateX) > Math.abs(this.maxTranX - 50) ){ return this.maxTranX }else{ return offsetX + this.boxTranslateX } } } // bindtouchend swiper.prototype.ontouchEnd = function(e, callback){ // 記錄手指離開屏幕的座標 this._x_end = e.changedTouches[0].pageX this._x_realOffset = this._x_end - this._x_start // 判斷滑動距離超過 指定值 輪播一張圖 var canExchangeImgFromOffset = Math.abs(this._x_realOffset) >= 50 ? true : false // 滑動距離達到 換圖的要求 if ( canExchangeImgFromOffset ){ // 變量說明 計算總偏移 var lastTotalTranlateX ; // 滑向上一張 if (this._x_offset > 0) { console.log('// 滑向上一張') // 判斷是否已經在第一張圖,若不是,則滑動上一張 if (Math.abs(this.boxTranslateX) > 0) { // lastTotalTranlateX 遞增 // this.singleOffsetX 爲負數 -- 得 + this.swiperIndex -= 1 lastTotalTranlateX = this.boxTranslateX - this.singleOffsetX } else { // 已在第一張圖 ,動畫恢復原位 this.swiperIndex = 0 lastTotalTranlateX = 0 } } // 滑向下一張 else { console.log('// 滑向下一張') if ( Math.abs(this.boxTranslateX) < Math.abs(this.maxTranX) ) { // lastTotalTranlateX 遞增 this.swiperIndex += 1 lastTotalTranlateX = this.boxTranslateX + this.singleOffsetX } else { console.log('到底圖了') this.swiperIndex = this.opt.imgLength -1 lastTotalTranlateX = this.maxTranX } } this.boxTranslateX = lastTotalTranlateX /* callback 說明 @參數1 是否執行動畫 @參數2 若參數1爲true, 則盒子的tranX 應該變成 lastTotalTranlateX,動畫飛到對應的圖 小程序 執行 wx.createAnimation */ callback && callback(true, lastTotalTranlateX) // reset 全部 與touch 相關參數 this.resetParams() } else{ callback && callback(false) // reset 全部 與touch 相關參數 this.resetParams() } }
源碼地址 https://gitee.com/adfasdfasdfas/XiaoChengXu-swiper-LunBodemo