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