摘要:最近一直在忙公司炒股大賽的頁面,終于在昨天把他給上線了。剛開始學(xué)習(xí)的時(shí)候,真心覺得無縫滾動(dòng)是一個(gè)神奇的功能。原理假如需要無縫滾動(dòng)的個(gè)元素是一個(gè)中的個(gè)。我們將控制在容器中滾動(dòng)。這樣無縫滾動(dòng)就已經(jīng)實(shí)現(xiàn)了。
最近一直在忙公司炒股大賽的頁面,終于在昨天把他給上線了。一個(gè)看似簡單的頁面,做起來才知道其中的艱辛,暗藏深坑。由于直接使用jquery來寫頁面邏輯,因此要比想象中復(fù)雜很多。無論是從布局,功能還是邏輯上來說,都有值得總結(jié)的地方。
這篇文章主要說說關(guān)于無縫滾動(dòng)的實(shí)現(xiàn)。
剛開始學(xué)習(xí)js的時(shí)候,真心覺得無縫滾動(dòng)是一個(gè)神奇的功能。背后到底是怎么回事?為什么明明只有幾個(gè)方塊就是滾不到頭?后來明白了原理之后,發(fā)現(xiàn)原來是通過一些障眼法來實(shí)現(xiàn)。
原理假如需要無縫滾動(dòng)的4個(gè)元素是一個(gè)ul.items中的6個(gè)li.item。我們將控制ul.items在容器.wrap中滾動(dòng)。html代碼如下:
ul.items表示className為items的ul元素,其他地方同理
我們的目標(biāo)是實(shí)現(xiàn)水平方向上的滾動(dòng),因此需要li.item水平排列。能夠達(dá)到目標(biāo)的方式常用的有使用float: left,或者使用display: inline-block。我們知道控制頁面元素的移動(dòng)無非就是控制元素的left, top, translateX, translateY,還有一種就是控制滾動(dòng)距離scrollTop, scrollLeft。布局的選擇,同時(shí)也會(huì)影響到j(luò)s控制屬性的選擇。
本例選擇使用display: inline-block布局,并控制ul.items的scrollLeft值,讓整個(gè)ul滾動(dòng)起來。布局上需要注意的有以下幾點(diǎn):
超出容器的部分需要隱藏,注意,此處的隱藏是給ul.items的,注意與float: left布局的差別。
.items { overflow: hidden; }
ul.items的內(nèi)容不能折行,因此
.items { white-space: nowrap; }
需要適配到移動(dòng)端,因此li.item的寬度就必然會(huì)隨著設(shè)配寬度的變小而變小。
@media (max-width: 780px) { .item { width: 190px; } } @media (max-width: 580px) { .item { width: 160px; } }
html布局中的是為了消除display: inline-block元素之間帶來的間隙。
那么無縫滾動(dòng)的障眼法到底是什么呢?本來用圖片描述會(huì)更加直觀一點(diǎn),不過這里我想偷個(gè)懶,用文字給大家講述一下,希望大家能看懂。
我們有子元素123456, 一個(gè)一個(gè)向左滾動(dòng),復(fù)制一份,就變成123456123456。如果我們在整體移動(dòng)到第二個(gè)1的時(shí)候,將整體的位置拉回到第一個(gè)1來,也就是初始位置,由于有div.items的overflow: hidden在,中間發(fā)生的變化我們沒辦法用肉眼識別出來,就感覺是一直在向左移動(dòng),永遠(yuǎn)都停不下來。
功能實(shí)現(xiàn)表達(dá)能力有限,如果沒懂再結(jié)合代碼理解一下吧,或者留言給我
一說到運(yùn)動(dòng),我們常常想到的方法可能是利用setTimeout或者setInterval, 不過呢,html5為我們提供了一個(gè)更加高性能的方法requestAnimationFrame。
在性能上,requestAnimationFrame > setTimeout > setInterval。具體原因大家可以找找相關(guān)的資料了解一下。而setTimeout的最小定時(shí)值為100/60,因此,我們在實(shí)現(xiàn)運(yùn)動(dòng)時(shí),從性能與兼容性兩方面考慮,常常會(huì)如下聲明:
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;
我們需要知道滾動(dòng)到什么位置回退到0,這個(gè)位置剛好就是復(fù)制之前所有子元素加一起的總長度。但是子元素的寬度會(huì)因?yàn)樵O(shè)備寬度的改變而改變,因此配合布局,我們需要作如下處理:
// 單個(gè)子元素的寬度 var itemW = 240; if ($items.children().eq(0).width() == 190) { itemW = 190; } if ($items.children().eq(0).width() == 160) { itemW = 160; } // 目標(biāo)位置 var target = itemW * $items.children().length;
為了實(shí)現(xiàn)障眼法,需要復(fù)制一份子元素
$items.html( $items.html() + $items.html() );
定義一個(gè)運(yùn)動(dòng)函數(shù),這里的運(yùn)動(dòng)為勻速運(yùn)動(dòng),因此比較簡單,只需要一直+1即可。如果需要運(yùn)動(dòng)快一點(diǎn),就多加一點(diǎn)
var timer = null; function adAni() { timer = nextFrame(function() { scrollX += 1; // 當(dāng)遞增到大于了目標(biāo)距離,就直接變?yōu)? if (scrollX >= target) { scrollX = 0; } $items.scrollLeft(scrollX); adAni(); }); } // 運(yùn)行這個(gè)函數(shù)就可以實(shí)現(xiàn)無縫滾動(dòng)啦。 adAni();
這樣無縫滾動(dòng)就已經(jīng)實(shí)現(xiàn)了。不過還有一些其他的需求。比如,鼠標(biāo)mouseover時(shí),需要停止?jié)L動(dòng),離開之后又要重新啟動(dòng)滾動(dòng)。因?yàn)樾枨蟮淖兓谝苿?dòng)端還需要能夠滑動(dòng)items.ul,手指松開之后繼續(xù)滾動(dòng)。因此我們需要一個(gè)區(qū)別pc于移動(dòng)端的函數(shù)。通過UA的不同來區(qū)分。
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端,鼠標(biāo)移入時(shí)停止,鼠標(biāo)移除時(shí)繼續(xù)滾動(dòng)
if (!isMobile()) { $items.on("mouseover", function() { cancelFrame(timer); }).on("mouseout", function() { adAni(); }); }
在移動(dòng)端,可以左右滑動(dòng),滑動(dòng)時(shí)停止自動(dòng)滾動(dòng),松開之后繼續(xù)自動(dòng)滾動(dòng)。移動(dòng)端的滑動(dòng)事件,主要通過touchstart, touchmove, touchend來實(shí)現(xiàn),與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(); })
那么到這里,就已經(jīng)基本搞定啦。雖然是一個(gè)比較簡單的小例子,但是其中也包含了一些常用的功能,比如使用requestAnimationFrame來實(shí)現(xiàn)運(yùn)動(dòng),移動(dòng)端的滑動(dòng)事件等。在這里總結(jié)一下分享給大家,有疑問歡迎探討。
實(shí)例地址:
http://codepen.io/yangbo5207/...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/79473.html
摘要:最全的配置大全,我已經(jīng)加了詳細(xì)中文注釋,只需要找到自己想要的配置就可以了,強(qiáng)烈建議收藏用法非常簡單,找到下的添加對象即可比如我要把規(guī)則原本單引號要變?yōu)殡p引號,那加上注意這個(gè)規(guī)則如果違反了規(guī)則情況下,這里的數(shù)字表示不不處理,表示警告,表示錯(cuò)誤 最全的eslint配置大全,我已經(jīng)加了詳細(xì)中文注釋,只需要找到自己想要的配置就可以了,強(qiáng)烈建議收藏! 用法非常簡單,找到.eslintrc.js下...
摘要:每一個(gè)項(xiàng)目,都要重寫驗(yàn)證規(guī)則,驗(yàn)證邏輯,那感覺簡直想屎。自從遇見了策略者模式,產(chǎn)經(jīng)你不是要加驗(yàn)證嗎沒問題。這個(gè)驗(yàn)證規(guī)則不行,替換沒問題。你這只是一對多的驗(yàn)證規(guī)則,當(dāng)我要提交表單的時(shí)候,我還有其他的都需要驗(yàn)證呢。 策略者模式 還在為你表單驗(yàn)證頭疼嗎?還在為產(chǎn)經(jīng)無理取鬧,要你每個(gè)輸入框都加驗(yàn)證而感到煩惱嗎?還在忙于復(fù)制粘貼驗(yàn)證規(guī)則而感到厭煩嗎? 那么策略者模式是最適合你的。What are...
摘要:讓你收獲滿滿碼個(gè)蛋從年月日推送第篇文章一年過去了已累積推文近篇文章,本文為年度精選,共計(jì)篇,按照類別整理便于讀者主題閱讀。本篇文章是今年的最后一篇技術(shù)文章,為了讓大家在家也能好好學(xué)習(xí),特此花了幾個(gè)小時(shí)整理了這些文章。 showImg(https://segmentfault.com/img/remote/1460000013241596); 讓你收獲滿滿! 碼個(gè)蛋從2017年02月20...
摘要:無論是因?yàn)橐苿?dòng)是企業(yè)內(nèi)部應(yīng)用無法外部使用,還是要求測試數(shù)據(jù)絕對私有化,專有云解決方案都可以支持。降低成本自動(dòng)化測試技術(shù)減少手工測試工作量。 摘要: MQC專有云解決方案是MQC測試體系的完全移植版,目標(biāo)是幫助客戶短期內(nèi)在搭建一套專業(yè)的、系統(tǒng)的自動(dòng)化測試平臺,實(shí)現(xiàn)測試服務(wù)、測試數(shù)據(jù)的完全本地化、私有化。無論是因?yàn)橐苿?dòng)App是企業(yè)內(nèi)部應(yīng)用無法外部使用,還是要求測試數(shù)據(jù)絕對私有化,MQC專有...
閱讀 1106·2021-11-23 10:05
閱讀 1785·2021-11-12 10:36
閱讀 1853·2019-08-30 15:56
閱讀 1684·2019-08-29 12:32
閱讀 3043·2019-08-28 18:04
閱讀 3428·2019-08-26 12:17
閱讀 2502·2019-08-26 11:35
閱讀 1240·2019-08-23 15:11