原生javascript模仿win8等待進度條。


一、序言

  一直很中意win8等待提示圓圈進度條。win8剛出來那會,感覺好神奇!苦於當時沒思路,沒去研究。通過最近網上找找資料,終於給搞出來了!先上Demo,獻丑了!預覽請看:win8進度條

二、簡單介紹

  原生javascript編寫,需要理解js基於面向對象編程和圓形坐標計算!

  實現原理:把每個圓點抽象成一個對象(ProgressBarWin8類型),將每個圓點對象存在數組中(progressArray),延遲執行每個圓點對象的run方法,至於圓點運行速度越來越快,是通過改變定時器延遲毫秒數實現的。

 // 判斷元素x與圓心x坐標大小,設置定時器延遲時間

if (this.position.left < this.fixed.left) {
    this.delay += .5;
} else {
    this.delay -= .5;
}

  還是上源碼吧!表達能力實在不怎么好(代碼中注釋更詳細,會看得更明白)。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>仿win8等待進度條</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background: green
        }
    </style>
</head>
<body>
    <script>
        //********准備條件******** 
        // 弧度角度轉換公式:弧度=Math.PI*角度/180; js中Math.sin(),Math.cos()等函數,是根據弧度計算
        // 圓x軸坐標計算公式:Math.cos(Math.PI * 角度/ 180) * 半徑 + 圓心x軸坐標
        // 圓y軸坐標計算公式:Math.sin(Math.PI * 角度/ 180) * 半徑 + 圓心y軸坐標
        //********准備條件******** 
        

        // 圓點元素類(js中沒有類的概念,這里模擬而已)
        function ProgressBarWin8() {
            // 圓心坐標
            this.fixed = {
                left: 0,
                top: 0
            };
            // html標簽元素坐標
            this.position = {
                left: 0,
                top: 0
            };
            this.radius = 70; // 圓半徑
            this.angle = 270; // 角度,默認270
            this.delay = 30; // 定時器延遲毫秒
            this.timer = null; // 定時器時間對象
            this.dom = null; // html標簽元素
            // html標簽元素樣式, position需設置成absolute
            this.style = {
                position: "absolute",
                width: "10px",
                height: "10px",
                background: "#fff",
                "border-radius": "5px"
            };
        }

        // js中每個函數都有個prototype對象屬性,每個實例都可以訪問
        ProgressBarWin8.prototype = {
            // 運行方法
            run: function() {
                if (this.timer) {
                    clearTimeout(this.timer);
                }
                
                // 設置html標簽元素坐標,即計算圓上的點x,y軸坐標
                this.position.left = Math.cos(Math.PI * this.angle / 180) * this.radius + this.fixed.left;
                this.position.top = Math.sin(Math.PI * this.angle / 180) * this.radius + this.fixed.top;
                this.dom.style.left = this.position.left + "px";
                this.dom.style.top = this.position.top + "px";
                
                // 改變角度
                this.angle++;
                
                // 判斷元素x與圓心x坐標大小,設置定時器延遲時間
                if (this.position.left < this.fixed.left) {
                    this.delay += .5;
                } else {
                    this.delay -= .5;
                }
                
                var scope = this;
                // 定時器,循環調用run方法,有點遞歸的感覺
                this.timer = setTimeout(function () {
                    // js中函數的調用this指向調用者,當前this是window
                    scope.run();
                }, this.delay);
            },
            // html標簽元素初始設置
            defaultSetting: function () {
                // 創建一個span元素
                this.dom = document.createElement("span");
                // 設置span元素的樣式,js中對象的遍歷是屬性
                for (var property in this.style) {
                    // js中對象方法可以用.操作符,也可以通過鍵值對的方式
                    this.dom.style[property] = this.style[property];
                }
                // innerWidth innerHeight窗口中文檔顯示區域的寬度,不包括邊框和滾動條,該屬性可讀可寫。
                // 設置圓心x,y軸坐標,當前可視區域的一般,即中心點
                this.fixed.left = window.innerWidth / 2;
                this.fixed.top = window.innerHeight / 2;
                // 設置span元素的初始坐標
                this.position.left = Math.cos(Math.PI * this.angle / 180) * this.radius + this.fixed.left;
                this.position.top = Math.sin(Math.PI * this.angle / 180) * this.radius + this.fixed.top;
                this.dom.style.left = this.position.left + "px";
                this.dom.style.top = this.position.top + "px";
                // 把span標簽添加到documet里面
                document.body.appendChild(this.dom);
                
                // 返回當前對象
                return this;
            }
        };

        // 不明白的,把后面的代碼注釋掉,先測試一個圓點運行情況
        //new ProgressBarWin8().defaultSetting().run();



        var progressArray = [], // 用於存放每個圓點元素對象數組,js中數組大小可變,類似於list集合
            tempArray = [], // 用於存放progressArray拋出來的每個對象,窗口大小改變后,重置每個對象的圓心坐標
            timer = 200; // 每隔多少毫秒執行一個元素對象run方法的定時器
        
        // 創建圓點元素對象,存入數組中,這里創建5個對象
        for (var i = 0; i < 5; ++i) {
            progressArray.push(new ProgressBarWin8().defaultSetting());
        }
        
        // 擴展數組each方法,c#中的lambda大都是這樣實現
        Array.prototype.each = function (fn) {
            for (var i = 0, len = this.length; i < len;) {
                // 通過call(object,arg1,arg2,...)/apply(object,[arg1,arg2,...])方法改變函數fn內this的作用域,  以此可用於繼承
                fn.call(this[i++], arguments);// 或者:fn.apply(this[i++],arguments)
            }
        };
        
        // 窗口大小改變事件,重置每個元素對象的圓心坐標
        window.onresize = function () {
            tempArray.each(function () {
                this.fixed.left = window.innerWidth / 2;
                this.fixed.top = window.innerHeight / 2;
            });
        };

        // 每個多少毫秒執行數組集合的元素對象run方法
        timer = setInterval(function () {
            if (progressArray.length <= 0) {
                // 清除此定時器,不然會一直執行(setTimeOut:延遲多少毫秒執行,一次;setInterval:每隔多少毫秒執行,多次)
                clearInterval(timer);
            } else {
                // shift() 方法用於把數組的第一個元素從其中刪除,並返回第一個元素的值。
                var entity = progressArray.shift();
                tempArray.push(entity);
                // 執行每個元素對象的run方法
                entity.run();
            }
        },timer);
    </script>
</body>
</html>

三、結束語:

  好就點個贊!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM