原生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>

三、结束语:

  好就点个赞!

你可能感兴趣的:(JavaScript)