近來沒有什麼值得寫的東西,空閑的時候幫前端的同學做了些大屏上的展示模塊,就放在這裡寫寫吧,手把手“需求->設計-> 實現”,受眾偏新手向。 為了直觀便於理解, 直接把結果貼在上面。 如上所示,基本需求比較簡單明瞭, “分頁顯示供應商、供應占比列表,自動輪播”。 一、需求評審 該有的環節還是要有,儘管 ...
近來沒有什麼值得寫的東西,空閑的時候幫前端的同學做了些大屏上的展示模塊,就放在這裡寫寫吧,手把手“需求->設計-> 實現”,受眾偏新手向。
為了直觀便於理解, 直接把結果貼在上面。
如上所示,基本需求比較簡單明瞭, “分頁顯示供應商、供應占比列表,自動輪播”。
一、需求評審
該有的環節還是要有,儘管需求簡單,評審不能省略,無論形式。開發的同學千萬不要真的相信需求就這麼簡單,否則南轅北轍,出力不討好,那必定是日常-_-||。
於是有豐富填坑經驗的開發同學,對於這個簡單的模塊需求,可能會提出如下的一些問題
1. 如果只有一頁,要不要輪播?
2.每頁的輪播間隔頻率是多少?
3.如果列表沒有數據,如何顯示這個模塊?
4.數據的刷新時機?是翻頁刷新,輪播一圈刷新,還是其他?
5.這個綠色的比值是什麼含義? 是不是還有紅色?
6.百分比的小數位?
7.如果介面異常比如網路不通,如何表示這種異常?
8.供應商的名字會不會有500字那麼長? 放不下如何佈局?
……等等
以上任何一個未明確的需求,都可能成為你編碼完成後的一個bug或優化建議。 o(* ̄︶ ̄*)o。
二、設計評審
關於上面待確認的每一個問題,我們偉大的產品經理都一一耐心的給出了“令人信服的”回答後。還是不能馬上開始編碼。下麵我們需要進行一些技術方案的設計討論,由技術leader把關。例如:
1. 數據流,這個列表的數據,是從資料庫中的哪幾個表取出的? 確認下查詢邏輯。
2.介面設計,是一次返回前端所有數據,還是支持分頁查詢。
3.性能考慮,查詢頻率是不是較高,併發是不是大,缺不缺索引,要不要上緩存?
4.輪播如何實現? 有沒有已經集成的輪播控制項,是否滿足要求,還是需要自己寫一個。
5.如何進行模塊化開發,作為一個模塊集成嵌入到整體頁面中。
……等等
明確了以上的問題後,作為前端同學的我,是不是可以開始擼代碼了?
三、想清楚再寫
說到這裡,
一類同學已經開始著手編碼了, 第一個想到需要寫的方法可能是,ajax 去後臺請求數據列表的介面。
另一類同學,可能仍在構思,如何組織代碼,提煉主要的數據結構和功能方法。
這裡我們顯然應該向“另外一類”同學學習。想清楚再寫,是一個毫無疑問的好習慣。
技術預研
實現一個功能,首先要掃除其中的未知技術點,掃除了所有未知之後,才能夠優化的組織實現方案。
上面的需求對於我這種半吊子前端來說,比較關鍵的兩個技術問題是。
1)用什麼方案來實現滑動動畫。 2)如何實現“無限滾動”。
滑動動畫——經過一番百度,總結下動畫可能的實現方案,包括用JS實現或者用CSS實現。 各有優劣,js 相容性好,控制靈活;CSS性能高,平滑流暢。因為我們的動畫非常線性,簡單,於是這裡我們決定採用CSS動畫作為動畫的實現方案。
通過簡單的研究,我們已經弄清楚了, 想讓一個頁面元素具有一個動畫效果,可以通過向他添加一個包含了動畫關鍵真的選擇器來實現,比如定義一個滑出動畫類,把這個css類加到元素上,元素就可以實現滑出的動畫效果。
無限滾動——思考下滾動頁面,雖然對於數據來說可能會分成很多頁,但對於屏幕展示來說,實際上最多同時出現兩個頁面,一個是前一頁,一個是當前頁。在不滾動的時候只有當前頁需要顯示。
順著這個思路, 滾動這個動作對應,“當前頁飛入”“前一頁飛出”這兩個細分動作,特別的情況是,初始顯示時,是沒有“前一頁”的。
那麼滾動這個動作大概思路就是,
1. 根據當前頁號取得對應數據,繪製HTML頁面,append到滾動區域,對其添加“飛入”動畫
2. 根據當前頁號取得上一頁頁面元素,對其添加“飛出”動畫,動畫結束後將其移除, 僅顯示當前頁。
四、編碼實現
終於到了編碼的時間了。
用到的 css 動畫類選擇器,以及關鍵幀
.slip_in_animation{ animation: slip_in 1s; } .slip_out_animation{ animation: slip_out 1s; } /*右側滑入*/ @keyframes slip_in { from {transform:translateX(100%);} to {transform:translateX(0);} } /*右側滑入*/ @keyframes slip_out { from {transform:translateX(0);} to {transform:translateX(-100%);} }
js應用於頁面元素,飛入飛出, 飛出後刪除,*動畫在結束後並不會改變元素實際位置。所以要在動畫結束前,移除元素,避免它回到之前位置,擋住當前頁,發生“閃爍”
//頁面滑入,要顯示的頁面 this.slipIn = function(pageNo){ $("#supplierListPage_"+pageNo).addClass("slip_in_animation"); }; //頁面滑出, this.slipOut = function(pageNo){ $("#supplierListPage_"+pageNo).addClass("slip_out_animation"); //移除上一頁,定時比動畫稍短,避免閃爍 setTimeout(function(){ $("#supplierListPage_"+pageNo).remove(); },900); };
翻頁的邏輯,第一次不滾動;滾到頭,把最後一頁飛出,第一頁飛入。
this.switchNext = function(pageNo){ //附加生成新的頁面 var newPageHtml = _this.makePageHtml(pageNo); $("#"+ _this.containerId).append(newPageHtml); //多於一頁的情況 if(_this.firtshow){ _this.firtshow= false; //第一次換頁 不需要移除之前頁面。 }else{ //前面已經有顯示過的頁面,需要把前面的頁面滾動出去。 var olderPage = pageNo -1; if(olderPage <=0){ //當前頁是第一個,前一頁就是最後一頁 olderPage = _this.totalPage; } _this.slipOut(olderPage); } _this.slipIn(pageNo); };
定時滾動到下一頁。如果是最後一頁,重新開始第一頁。
this.startRolling = function(){ _this.switchNext(_this.curPage); //按間隔輪播 _this.switchTimer = setInterval(function(){ if(_this.totalPage == 1) return; if(_this.curPage < _this.totalPage) { _this.curPage++; }else{ _this.curPage = 1; } _this.switchNext(_this.curPage); },_this.switchInterval); };
寫到這裡,下麵是完整代碼,需要的可以參考。
完整的代碼CSS:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
.slip_in_animation{ animation: slip_in 1s; } .slip_out_animation{ animation: slip_out 1s; } /*右側滑入*/ @keyframes slip_in { from {transform:translateX(100%);} to {transform:translateX(0);} } /*右側滑入*/ @keyframes slip_out { from {transform:translateX(0);} to {transform:translateX(-100%);} }View Code
完整JS:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
function SupplierListTable(){ var _this = this; //echart 圖表對象。 //輪播間隔 毫秒 this.switchInterval = 5000; //當前輪播的頁,從1開始 this.curPage=1; //每頁條數 this.pageSize = 5; //當前數據對應總頁數 this.totalPage = 0; //數據列表 this.chartDataList = new Array(); //第一次展示標誌 this.firtshow =true; this.containerId = null; //輪播定時器 this.switchTimer = null; this.init = function(containerId){ _this.containerId = containerId; //初始化圖表 $("#"+containerId).html(""); _this.reloadData(containerId); }; this.getTotalPage = function(){ var totalPage = Math.ceil(_this.chartDataList.length/_this.pageSize); return totalPage; }; this.reloadData =function(containerId){ //從網路請求數據。 setTimeout(function(){ _this.chartDataList= [ {name:"供應商1",percent:"12%"}, {name:"供應商2",percent:"13%"}, {name:"供應商3",percent:"14%"}, {name:"供應商4",percent:"15%"}, {name:"供應商5",percent:"16%"}, {name:"供應商6",percent:"13%"}, {name:"供應商7",percent:"14%"}, {name:"供應商8",percent:"15%"}, {name:"供應商9",percent:"16%"} ]; _this.totalPage = _this.getTotalPage(); _this.curPage = 1; _this.stopRolling(); _this.startRolling(); },300); }; this.stopRolling= function(){ if(_this.switchTimer != null){ clearInterval(_this.switchTimer); _this.switchTimer = null; _this.curPage = 0; } }; this.startRolling = function(){ _this.switchNext(_this.curPage); //按間隔輪播 _this.switchTimer = setInterval(function(){ if(_this.totalPage == 1) return; if(_this.curPage < _this.totalPage) { _this.curPage++; }else{ _this.curPage = 1; } _this.switchNext(_this.curPage); },_this.switchInterval); }; this.switchNext = function(pageNo){ //附加生成新的頁面 var newPageHtml = _this.makePageHtml(pageNo); $("#"+ _this.containerId).append(newPageHtml); //多於一頁的情況 if(_this.firtshow){ _this.firtshow= false; //第一次換頁 不需要移除之前頁面。 }else{ //前面已經有顯示過的頁面,需要把前面的頁面滾動出去。 var olderPage = pageNo -1; if(olderPage <=0){ //當前頁是第一個,前一頁就是最後一頁 olderPage = _this.totalPage; } _this.slipOut(olderPage); } _this.slipIn(pageNo); }; //生成指定頁的html。 this.makePageHtml = function(pageNo){ var startRecIndex= _this.pageSize * (pageNo - 1); var endRecIndex = _this.pageSize * pageNo ; if(endRecIndex > _this.chartDataList.length){ endRecIndex = _this.chartDataList.length; } var html = "<div style='width: 100%; box-sizing: border-box;position: absolute;padding: 20px;' id='supplierListPage_" +pageNo+"'>"; for (var i = startRecIndex; i < endRecIndex; i++) { html+= "<div style=' margin-bottom: 10px ;border-bottom: 1px solid #484752;'><span style='color: white'>" +_this.chartDataList[i].name+"</span> <span style='float: right;color: #0c9c6e'>"+_this.chartDataList[i].percent+"</span></div>" } html+="</div>" return html; }; //頁面滑入,要顯示的頁面 this.slipIn = function(pageNo){ $("#supplierListPage_"+pageNo).addClass("slip_in_animation"); }; //頁面滑出, this.slipOut = function(pageNo){ $("#supplierListPage_"+pageNo).addClass("slip_out_animation"); //移除上一頁,定時比動畫稍短,避免閃爍 setTimeout(function(){ $("#supplierListPage_"+pageNo).remove(); },900); }; } $(document).ready(function(){ var containerId = 'supplierListChart'; var supplierListTable = new SupplierListTable(); supplierListTable.init(containerId); });View Code
HTML頁面容器:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div style="height: 300px;width:400px;overflow-x: hidden;position: relative" id="supplierListChart" > </div>View Code
本文來自博客園,作者:鍋叔
轉載請註明原文鏈接:https://www.cnblogs.com/uncleguo/p/16809968.html