摘要:為了模擬原生應(yīng)用的觸控效果,大量的應(yīng)用使用了手指跟隨的滑動(dòng)效果,也就是用手指滑動(dòng)幻燈片的效果,什么是手指跟隨如圖網(wǎng)上滑動(dòng)插件有不少,但好像沒一個(gè)好用的不是太多,就是不靈活這里用原生實(shí)現(xiàn)了該功能,不僅代碼量不多,邏輯也較簡(jiǎn)單。
為了模擬原生應(yīng)用的觸控效果,大量的“H5”應(yīng)用使用了手指跟隨的滑動(dòng)效果,也就是用手指滑動(dòng)幻燈片的效果, 什么是手指跟隨,如圖;
網(wǎng)上滑動(dòng)插件有不少,但好像沒一個(gè)好用的(不是bug太多,就是不靈活)這里用原生JS實(shí)現(xiàn)了該功能,不僅代碼量不多,邏輯也較簡(jiǎn)單。移動(dòng)端H5頁(yè)面的觸控觸發(fā)事件在我之前的一篇博客中寫了挺多.原博地址原生JS實(shí)現(xiàn)觸控滑動(dòng)(swipe)圖片輪播 (里面大致羅列了HTML5中touch事件的使用方法)
這里寫的PageSlide的使用的方法是將HTML結(jié)構(gòu)寫好后往里傳參就可以了.它接受所有滑動(dòng)頁(yè)面對(duì)象(在這里是document.querySelector("#pages") ) 和要設(shè)定的方向(用X,Y表示橫向或者縱向)以及一個(gè)可選的擴(kuò)展函數(shù).
DEMO在此(使用模擬器或者移動(dòng)設(shè)備打開預(yù)覽):
移動(dòng)端原生JS實(shí)現(xiàn)手指跟隨的觸控滑動(dòng)(縱向)
移動(dòng)端原生JS實(shí)現(xiàn)手指跟隨的觸控滑動(dòng)(橫向)
直接下載代碼出門左轉(zhuǎn)Github? PageSlideDemo
掃碼看DEMO(縱向):
這里將所有的代碼都封裝進(jìn)一個(gè)PageSlide的原型對(duì)象中,可以當(dāng)成原生JS插件來(lái)使用,它所要求的HTML的結(jié)構(gòu)為:
// 所有滑動(dòng)頁(yè)面的容器content//所有滑動(dòng)單頁(yè)...animation element
CSS樣式結(jié)構(gòu)為:
/* 注意加html標(biāo)簽,使得高度100%等于視窗高度 */ html,body{ width:100%; height:100%; margin:0 ; padding:0 ; overflow:hidden; …… } .pages{ width: 100%; height: 100%; position: relative; …… } .page { /*滑動(dòng)頁(yè)面的統(tǒng)一樣式 */ position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; transform: translate3d(0px, 100%, 0px); -webkit-transform: translate3d(0px, 100%, 0px); transition: transform .5s ease-out; -webkit-transition: -webkit-transform .5s ease-out; } .page1{……} .page2{……} .page3{……} /* 所有動(dòng)畫使用類控制 */ .play .myAnimation { ... }
要實(shí)現(xiàn)手指跟隨的滑動(dòng)效果, 關(guān)鍵在于通過touch事件來(lái)設(shè)置transform:translate3d(x,y,z)的參數(shù),并在滑動(dòng)結(jié)束(touchend)設(shè)置一個(gè)最小滑動(dòng)距離minRange,該距離范圍內(nèi)的滑動(dòng),translate3d的參數(shù)等于touchmove的滑動(dòng)距離,當(dāng)大于minRange時(shí), 則觸發(fā)下一頁(yè)(或上一頁(yè))的整體滑動(dòng),translate3d的X或Y的參數(shù)也就是視窗的寬(橫向滑動(dòng)時(shí))或者高(縱向滑動(dòng)時(shí))
另外,對(duì)于一個(gè)網(wǎng)頁(yè)app,還需要解決一個(gè)問題,即每個(gè)頁(yè)面中可能有動(dòng)畫或者其他的事件需要在該頁(yè)面出現(xiàn)時(shí)才開始播放,動(dòng)畫采用css類控制, 這里采用在每個(gè)當(dāng)前頁(yè)面中添加一個(gè).play的類作為標(biāo)記, 在每個(gè)頁(yè)面的CSS動(dòng)畫設(shè)置中,同樣加上.play類名,這樣就實(shí)現(xiàn)了當(dāng)頁(yè)面出現(xiàn)才開始播放本頁(yè)動(dòng)畫的功能。
PageSlide的代碼解析如下:
// PageSlide接收三個(gè)參數(shù):頁(yè)面元素,要設(shè)定的滑動(dòng)方向,可選的擴(kuò)展函數(shù) var PageSlide = function(el, swipe, options) { this.options = options || {} //可選函數(shù) this.current = 0 //當(dāng)前頁(yè)面索引 this.pageX //橫向的手指落點(diǎn) this.pageY //縱向的手指落點(diǎn) this.height //設(shè)備高度 this.width //設(shè)備寬度 this.flag //判斷滑動(dòng)方向的變量 this.move //滑動(dòng)的距離 this.$el = el //當(dāng)前頁(yè)面的對(duì)象 this.swipe = swipe || "X" //滑動(dòng)方向參數(shù) this.resize().init().bindEvents() //初始化 } PageSlide.prototype.init = function(i) { var current = i ? this.$el.children[i] : this.$el.firstElementChild if (!current) throw "ERROR"; //moving類名作為當(dāng)前滑動(dòng)頁(yè)面的標(biāo)記,也在樣式中作滑動(dòng)的擴(kuò)展效果 current.classList.add("moving") current.style.webkitTransform = "translate3d(0,0,0)" //以swipe的值預(yù)設(shè)置其他頁(yè)面的寬高,獲得流暢的交互效果 for(var i = 1; iMath.abs(Y) ? "X" : "Y" if (this.flag === this.swipe) { current.classList.add("moving") next && next.classList.add("moving") prev && prev.classList.add("moving") } } if (this.flag === this.swipe) { e.preventDefault() e.stopPropagation() switch (this.swipe) { case "X": //swipe horizontal this.move = X this.setX(current, X) next && (this.setX(next, X + this.width)) prev && (this.setX(prev, X - this.width)) break; case "Y": //swipe vertical this.move = Y this.setY(current, Y) next && (this.setY(next, Y + this.height)) prev && (this.setY(prev, Y - this.height)) break; } } } PageSlide.prototype.touchend = function(e) { var minRange = 50 var move = this.move var current = this.getCurrent() var next = current.nextElementSibling var prev = current.previousElementSibling current.classList.remove("moving") next && next.classList.remove("moving") prev && prev.classList.remove("moving") if (!this.flag) return e.preventDefault() //滑動(dòng)結(jié)束前往下一頁(yè)面,next()方法調(diào)用了go()方法 if (move < -minRange && next) return this.next() if (move > minRange && prev) return this.prev() this.reset() } PageSlide.prototype.touchcancel = function(e) { var current = this.getCurrent() var next = current.nextElementSibling var prev = current.previousElementSibling current.classList.remove("moving") next && next.classList.remove("moving") prev && prev.classList.remove("moving") this.reset() } //動(dòng)態(tài)設(shè)定translate3d參數(shù)方法 PageSlide.prototype.setX = function(el, x, unit) { el && (el.style.webkitTransform = "translate3d(" + x + (unit || "px") + ",0,0)") } PageSlide.prototype.setY = function(el, y, unit) { el && (el.style.webkitTransform = "translate3d(0," + y + (unit || "px") + ",0)") } //設(shè)置當(dāng)前觸控頁(yè)面translate3d參數(shù)為0的方法 PageSlide.prototype.setCurrent = function(el, i) { el && (el.style.webkitTransform = "translate3d(0,0,0)") if (i) { this.current = i this.$current = this.$el.children[i] } } //調(diào)用go()方法前往下一或上一頁(yè)面 PageSlide.prototype.next = function() { this.go(this.current + 1) } PageSlide.prototype.prev = function() { this.go(this.current - 1) } //重置方法,用于初始化以及當(dāng)前頁(yè)面的重置 PageSlide.prototype.reset = function() { var width = this.width var height = this.height var swipe = this.swipe var current = this.getCurrent() var prev = current.previousElementSibling var next = current.nextElementSibling this.setCurrent(current) prev && (this["set" + swipe](prev, -(swipe === "X" ? width : height))) next && (this["set" + swipe](next, swipe === "X" ? width : height)) } //去往下一或上一頁(yè)面的go方法 PageSlide.prototype.go = function(i) { var onFinish = this.options.onFinish var current = this.getCurrent() var total = this.$el.childElementCount var target = this.$el.children[i] var d = i < this.current ? -1 : 1 if (i === this.current || i < 0 || i >= total) return if (onFinish && (typeof onFinish === "function")) onFinish.call(this, i) // 滑動(dòng)完成調(diào)用方法 typeof this.options.tranSetionEnd ==="function" && this.options.tranSetionEnd.call(this) this.current = i this["set" + this.swipe](current, -d * (this.swipe === "X" ? this.width : this.height)) this.setCurrent(target, i) this.finish(current, target) } //滑動(dòng)完成后刪除當(dāng)前頁(yè)面.play標(biāo)記以及為下一頁(yè)面添加.play標(biāo)記 PageSlide.prototype.finish = function(curr, target) { this.flag = null setTimeout(function() { curr && curr.classList.remove("play") target && target.classList.add("play") }, 3e2) } /*direct to a page */ //直達(dá)某一頁(yè)面的方法, 因?yàn)橛袀€(gè)項(xiàng)目的需要,寫了這個(gè)方法,要從任意頁(yè)面開始滑動(dòng)依然能保持正常的滑動(dòng)體驗(yàn),就需要將直達(dá)頁(yè)面的前面所有頁(yè)面的translate3d參數(shù)都設(shè)置為(0,-height,0) PageSlide.prototype.direct = function(i){ if(i&&typeof(i)==="number") { this.go(i) for(var j = 0; j< i ;j++) { this["set" + this.swipe](this.$el.children[j], -1 * (this.swipe === "X" ? this.width : this.height)) } } else return }
總算寫完了,吃飯~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/86019.html
摘要:把事件統(tǒng)一起來(lái)處理用戶的輸入要用到事件。就這樣,提取了鼠標(biāo)觸摸屏觸控筆的共通之處,以方便開發(fā)跨設(shè)備的應(yīng)用。雖然是一個(gè)抽象,但它包含了鼠標(biāo)觸摸屏觸控筆的全部?jī)?nèi)容。手指與觸摸屏的屏幕接觸著,認(rèn)定為。 跨設(shè)備的問題 平時(shí)我們?cè)陔娔X上訪問的網(wǎng)頁(yè),大部分情況下是用鼠標(biāo)來(lái)控制的。比如說(shuō)鏈接跳轉(zhuǎn),就是鼠標(biāo)指針移動(dòng)到鏈接文字或圖片的位置,然后點(diǎn)擊一下。又比如說(shuō)滾動(dòng)屏幕,滑動(dòng)一下鼠標(biāo)滾輪就可以。 如果是...
摘要:把事件統(tǒng)一起來(lái)處理用戶的輸入要用到事件。就這樣,提取了鼠標(biāo)觸摸屏觸控筆的共通之處,以方便開發(fā)跨設(shè)備的應(yīng)用。雖然是一個(gè)抽象,但它包含了鼠標(biāo)觸摸屏觸控筆的全部?jī)?nèi)容。手指與觸摸屏的屏幕接觸著,認(rèn)定為。 跨設(shè)備的問題 平時(shí)我們?cè)陔娔X上訪問的網(wǎng)頁(yè),大部分情況下是用鼠標(biāo)來(lái)控制的。比如說(shuō)鏈接跳轉(zhuǎn),就是鼠標(biāo)指針移動(dòng)到鏈接文字或圖片的位置,然后點(diǎn)擊一下。又比如說(shuō)滾動(dòng)屏幕,滑動(dòng)一下鼠標(biāo)滾輪就可以。 如果是...
摘要:并且除了常用的端,還要考慮微信端,或者是端。所以我們要有一套機(jī)制,在端上走的代碼,在端或者微信端上走端對(duì)應(yīng)的代碼。對(duì)于一個(gè)從零開始的移動(dòng)端項(xiàng)目,我總結(jié)了以上這些移動(dòng)開發(fā)難點(diǎn),希望之后的人能少踩點(diǎn)坑,站在我的肩膀上提高項(xiàng)目開發(fā)的效率和質(zhì)量。 從零搭建移動(dòng)H5開發(fā)項(xiàng)目實(shí)戰(zhàn) 前端H5的前世今身 在Pc的時(shí)代,前端技術(shù)無(wú)疑統(tǒng)治了大多數(shù)用戶的交互界面!而在移動(dòng)為王的今天,NA開發(fā)在早期占領(lǐng)了大多...
摘要:并且除了常用的端,還要考慮微信端,或者是端。所以我們要有一套機(jī)制,在端上走的代碼,在端或者微信端上走端對(duì)應(yīng)的代碼。對(duì)于一個(gè)從零開始的移動(dòng)端項(xiàng)目,我總結(jié)了以上這些移動(dòng)開發(fā)難點(diǎn),希望之后的人能少踩點(diǎn)坑,站在我的肩膀上提高項(xiàng)目開發(fā)的效率和質(zhì)量。 從零搭建移動(dòng)H5開發(fā)項(xiàng)目實(shí)戰(zhàn) 前端H5的前世今身 在Pc的時(shí)代,前端技術(shù)無(wú)疑統(tǒng)治了大多數(shù)用戶的交互界面!而在移動(dòng)為王的今天,NA開發(fā)在早期占領(lǐng)了大多...
閱讀 840·2021-09-22 15:18
閱讀 1196·2021-09-09 09:33
閱讀 2766·2019-08-30 10:56
閱讀 1202·2019-08-29 16:30
閱讀 1498·2019-08-29 13:02
閱讀 1470·2019-08-26 13:55
閱讀 1652·2019-08-26 13:41
閱讀 1949·2019-08-26 11:56