一、序言
一直很中意win8等待提示圓圈進度條。 win8剛出來那會,感覺好神奇!苦於當時沒思路,沒去研究。透過最近網路找找資料,終於給搞出來了!先上Demo,獻醜了!預覽請看:win8進度條。
二、簡單介紹
原生javascript編寫,需要理解js基於物件導向程式設計和圓形座標計算!
實作原理:把每個圓點抽象化成物件(ProgressBarWin8型別),將每個圓點物件存在陣列中(progressArray),延遲執行每個圓點物件的run方法,至於圓點運行速度越來越快,是透過改變定時器延遲毫秒數來實現的。
// 判斷元素x與圓心x座標大小,設定元定時器延遲時間
if (this.position.left this.delay = .5;
} else {
this.delay -= .5;
}
還是上源碼吧!表達能力實在不怎麼好(程式碼中註解更詳細,會看得更明白)。
仿win8等待進度條
<script> <BR>// ********準備條件******** <BR>// 弧度角度轉換公式:弧度=Math.PI*角度/180; js中Math.sin(),Math.cos( )等函數,是根據弧度計算<BR>// 圓x軸座標計算公式:Math.cos(Math.PI * 角度/ 180) * 半徑圓心x軸座標<BR>// 圓y軸座標計算公式: Math.sin(Math.PI * 角度/ 180) * 半徑圓心y軸座標<BR>//********準備條件******** <br><br><BR> // 圓點元素類別(js沒有類別的概念,這裡模擬而已) <BR>function ProgressBarWin8() { <BR>// 圓心座標<BR>this.fixed = { <BR>left: 0, <BR>top: 0 <BR>}; <BR>// html標籤元素座標<BR>this.position = { <BR>left: 0, <BR>top: 0 <BR>}; <BR>this.radius = 70; // 圓半徑<BR>this.angle = 270; // 角度,預設270 <BR>this.delay = 30; // 定時器延遲毫秒<BR>this.timer = null; // 定時器時間物件<BR>this.dom = null; // html標籤元素<BR>// html標籤元素樣式, position需設定為absolute <BR>this.style = { <BR>position: "absolute", <BR>width: "10px", <BR>height: "10px", <BR>background: "#fff", <BR>"border-radius": "5px" <BR>}; <BR>} <br> <br>// js中每個函數都有prototype物件屬性,每個實例都可以存取<BR>ProgressBarWin8.prototype = { <BR>// 運行方法<BR>run: function() { <BR> if (this.timer) { <BR>clearTimeout(this.timer); <BR>} <br><br>// 設定html標籤元素座標,即計算圓上的點x,y軸座標<BR>this .position.left = Math.cos(Math.PI * this.angle / 180) * this.radius this.fixed.left; <BR>this.position.top = Math.sin(Math.PI * this.angle / 180) * this.radius this.fixed.top; <BR>this.dom.style.left = this.position.left "px"; <BR>this.dom.style.top = this.position.top "px "; <br><br>// 改變角度<BR>this.angle ; <br><br>// 判斷元素x與圓心x座標大小,設定定時器延遲時間<BR>if (this.position. left < this.fixed.left) { <BR>this.delay = .5; <BR>} else { <BR>this.delay -= .5; <BR>} <br><br>var scope = this ; <BR>// 定時器,循環呼叫run方法,有點遞歸的感覺<BR>this.timer = setTimeout(function () { <BR>// js中函數的呼叫this指向呼叫者,當前this是window <BR>scope.run(); <BR>}, this.delay); <BR>}, <BR>// html標籤元素初始設定<BR>defaultSetting: function () { <BR>// 建立一個span元素<BR>this.dom = document.createElement("span"); <BR>// 設定span元素的樣式,js中物件的遍歷是屬性<BR>for (var property in this.style) { <BR>// js中物件方法可以用.操作符,也可以透過鍵值對的方式<BR>this.dom.style[property] = this.style[property]; <BR>} <BR>// innerWidth innerHeight視窗中文件顯示區域的寬度,不包括邊框和捲軸,該屬性可讀可寫入。<BR>// 設定圓心x,y軸座標,目前視覺區域的一般,即中心點<BR>this.fixed.left = window.innerWidth / 2; <BR>this.fixed.top = window.innerHeight / 2; <BR>// 設定span元素的初始座標<BR>this.position.left = Math.cos(Math.PI * this.angle / 180) * this.radius this.fixed.left; <BR> this.position.top = Math.sin(Math.PI * this.angle / 180) * this.radius this.fixed.top; <BR>this.dom.style.left = this.position.left "px"; <BR>this.dom.style.top = this.position.top "px"; <BR>// 把span標籤加到documet裡面<BR>document.body.appendChild(this.dom); <br><br>// 回傳目前物件<BR>return this; <BR>} <BR>}; <br><br>// 不明白的,把後面的程式碼註解掉,先測試一個圓點運作情況<BR>//new ProgressBarWin8().defaultSetting().run(); <br><br><br><br>var progressArray = [], // 用於存放每個圓點元素物件數組,js中數組大小可變,類似於list集合<BR>tempArray = [], // 用於存放progressArray拋出的每個對象,窗口大小改變後,重置每個對象的圓心坐標<BR>timer = 200; / / 每隔多少毫秒執行一個元素對象run方法的定時器<br><br>// 創建圓點元素對象,存入數組中,這裡創建5個對象<BR>for (var i = 0; i < 5; i) { <BR>progressArray.push(new ProgressBarWin8().defaultSetting()); <BR>} <br><br>// 擴充陣列each方法,c#中的lambda大都是這樣實作<BR> Array.prototype.each = function (fn) { <BR>for (var i = 0, len = this.length; i < len;) { <BR>// 通過call(object,arg1,arg2,... )/apply(object,[arg1,arg2,...])方法改變函數fn內this的作用域, 以此可用於繼承<BR>fn.call(this[i ], arguments);// 或: fn.apply(this[i ],arguments) <BR>} <BR>}; <br><br>// 視窗大小改變事件,重置每個元素物件的圓心座標<BR>window.onresize = function () { <BR>tempArray.each(function () { <BR>this.fixed.left = window.innerWidth / 2; <BR>this.fixed.top = window.innerHeight / 2; <BR>this.fixed.top = window.innerHeight / 2; <BR>}); <br>}; <br><BR>// 每個多少毫秒執行陣列集合的元素物件run方法<BR>timer = setInterval(function () { <BR>if (progressArray.length <= 0) { <BR>// 清除此定時器,不然會一直執行(setTimeOut:延遲多少毫秒執行,一次;setInterval:每隔多少毫秒執行,多次) <BR>clearInterval(timer); <BR>} else { <BR>// shift() 方法用來把陣列的第一個元素從其中刪除,並傳回第一個元素的值。 <BR>var entity = progressArray.shift(); <BR>tempArray.push(entity); <BR>// 執行每個元素物件的run方法<BR>entity.run(); <BR>} <BR>},timer); <BR></script>