JS 面向对象 实现烟花特效

基本效果如图:

  JS 面向对象 实现烟花特效

  这里的烟花特效 是配合鼠标点击去实现的  (你要是想绑定别的事件也可)

  1. 创建一个烟花,从底部升起运动到目标位置
  2. 到达目标位置之后,删除它的同时 炸出一堆烟花

 

HTML布局+CSS样式

    <div class="container"></div>
 1     <style>
 2         .container{
 3             width: 80%;
 4             height: 300px;
 5             border: 2px solid red;
 6             background: #000;
 7             margin:20px auto;
 8             cursor: pointer;
 9             position: relative;
10             left: 0;
11             top: 0;
12             overflow: hidden;
13         }
14         .fire{
15             width: 10px;
16             height:10px;
17             position: absolute;
18             bottom: 0;
19         }
20     </style>

JavaScript 代码

  1     <script>
  2     // OOA
  3         // 1.创建一个烟花元素
  4         // 2.元素运动 运动结束之后删除
  5         // 3.烟花爆炸 循环多个烟花  爆炸之后也要删除
  6         // 4.随机位置
  7         // 5.烟花的随机颜色
  8     // OOD
  9         // function Firework(x,y){
 10         //     this.init(x,y);
 11         // }
 12         
 13         // Firework.prototype = {
 14         //     constructor : Firework,
 15         //     // 初始化
 16         //     init : function(x,y){//xy是目标位置
 17         //         // 创建元素
 18         //         // 元素运动  把目标点当做参数x、y
 19         //         // 调用函数
 20 
 21         //     },
 22         //     // 1.创建元素
 23         //     createFireWorkEle : function(){
 24 
 25         //     },
 26         //     // 2.元素运动
 27         //     fireWorkUp : function(ele){
 28         //         // 2部分运动 left直接到达、top运动达到
 29         //     },
 30         //     // 3.烟花爆炸
 31         //     fireWorkBlast : function(){
 32         //         // 3.1创建非常多的元素
 33         //     },
 34         //     // 4.随机位置
 35         //     randomBoundary : function(){
 36 
 37         //     },
 38         //     // 5.随机颜色
 39         //     randomColor : function(ele){
 40 
 41         //     }
 42         // }
 43 
 44     // OOP
 45         function Firework(x,y , selector){
 46             // 选择父级元素
 47             this.main = document.querySelector(selector);
 48             
 49             this.init(x,y);
 50         }
 51         
 52         Firework.prototype = {
 53             constructor : Firework,
 54             // 初始化
 55             init : function(x,y){
 56                 //x、y是点击事件创建的烟花的位置
 57                 this.x = x;
 58                 this.y = y;
 59 
 60                 // 创建元素
 61                 this.ele = this.createFireWorkEle();
 62                 // 爆炸烟花的随机位置 最大值
 63                 this.left_max = this.main.offsetWidth - this.ele.offsetWidth;
 64                 this.top_max = this.main.offsetHeight - this.ele.offsetHeight;
 65 
 66                 // 元素添加背景色
 67                 this.randomColor(this.ele);
 68                 // 烟花主体升起
 69                 this.fireWorkUp(this.ele );
 70                 // 烟花爆炸
 71                 this.fireWorkBlast(this.ele);
 72             },
 73             // 1.创建元素
 74             createFireWorkEle : function(){
 75                 // 往containe里面放进一个烟花fire
 76                 var ele = document.createElement("div");
 77                 ele.className = "fire";
 78                 // 在页面显示 
 79                 this.main.appendChild(ele);
 80                 return ele;
 81             },
 82             // 2.元素运动
 83             fireWorkUp : function(ele){
 84                 // 两部分的运动 left直接到达、top运动达到
 85                 ele.style.left = this.x + "px";
 86                 animate(ele, {top : this.y} , function(){
 87                     // 烟花运动结束后 要删除它
 88                     // console.log(this);//这时候指向windoe,用bind修改指向
 89                     ele.remove();
 90                     // 然后调用烟花爆炸
 91                     this.fireWorkBlast();
 92                 }.bind(this));
 93             },
 94             // 3.烟花爆炸
 95             fireWorkBlast : function(){
 96                 // 3.1创建非常多的元素
 97                 for(var i = 0 ; i < 20 ; i ++){
 98                     var ele = this.createFireWorkEle();
 99                     this.randomColor(ele);
100                     // 3.1初始样式设置
101                     ele.style.left = this.x + "px";
102                     ele.style.top = this.y + "px";
103                     // 和点击之后创建的烟花 区分开
104                     ele.style.borderRadius = "50%";
105                     // 3.3让元素有运动目标
106                     animate(ele , this.randomBoundary(ele) , function(callback_ele){
107                         // 爆炸之后删除所有元素
108                         // 用bind 给每个匿名函数都绑定一个ele。否则只会删除最后一个ele
109                         callback_ele.remove();
110                     }.bind(this , ele));
111                 }
112             },
113             // 4.随机位置
114             randomBoundary : function(){
115                 // min 是0 
116                 // max中offset性能消耗大,所以放在init()里,只获取一次即可
117                 return{
118                     left : parseInt(Math.random()*(this.left_max + 1)),
119                     top : parseInt(Math.random()*(this.top_max + 1))
120                 }
121             },
122             // 5.随机颜色
123             randomColor : function(ele){
124                 // 随机颜色方法很多
125                 var r = parseInt(256 * Math.random());
126                 var g = parseInt(256 * Math.random());
127                 var b = parseInt(256 * Math.random());
128                 var random_color = "rgb("+r + "," + g + "," + b +")";
129                 return ele.style.backgroundColor = random_color;
130                 
131             }
132         }
133 
134         document.querySelector(".container").addEventListener("click",function(evt){
135             var e = evt || event;
136             new Firework(e.offsetX , e.offsetY , ".container");
137         })
138     </script>

<script>引入的 "animate.js"  运动封装

 

 1 //               元素,属性,回调函数(动画执行结束,调用这个函数)
 2 function animate( ele , attr_options , callback ){
 3     // 获取当前属性
 4     for(var attr in attr_options){
 5         // 同时判断是否是opacity属性
 6         attr_options[attr] = {
 7             // 目标点(传入的数据)
 8             target : attr === "opacity" ? attr_options[attr] * 100 : attr_options[attr],
 9             // 元素当前的属性值
10             iNow   : attr === "opacity" ? parseInt( getComputedStyle(ele)[attr] * 100 ) : parseInt( getComputedStyle(ele)[attr])
11         }
12     }
13     // 定时器的开启和关闭
14     clearInterval( ele.timer );
15     ele.timer = setInterval( function(){
16         // 获取运动所必须的值
17         for(var attr in attr_options){
18             // 取出每一条数据
19             var item = attr_options[attr];
20             // console.log(item , attr);//target和iNow , "属性名"
21             var target = item.target;
22             var iNow   = item.iNow;
23             // 计算速度
24             var speed = (target - iNow) / 10;
25             // 速度取整
26             speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
27             // 运动的终止条件  
28             // (目标 - 当前位置) 的绝对值 <= 速度 , 此时判定已经到达
29             if( Math.abs( target - iNow) <= Math.abs(speed) ){
30                 // 送他到底目标点
31                 ele.style[attr] = attr === "opacity" ? target / 100 :  target + "px";
32                 // if里的终止条件不严谨:
33                 // 因为目标的不一致会让运动次数执行不同,有可能会提前关闭定时器
34                 // 解决办法:完成一条运动后 删除对象里的数据
35                 delete attr_options[attr];
36             
37                 for(var num in attr_options){
38                     // 如果attr_options里面有属性,不终止定时器
39                     return false;
40                 }
41                 // 如果对象里面没有属性了,就可以关闭定时器
42                 clearInterval(ele.timer);
43                 // 可能会不传callback
44                 typeof callback === "function" ? callback() : "";
45             }else{
46                 // 元素继续运动
47                 // 如果直接设置iNow 每次循环iNow都会被重置,iNow是一个临时变量
48                 // 所以不能去操作iNow,要去操作iNow的数据源
49                 attr_options[attr].iNow += speed;
50                 ele.style[attr] = attr === "opacity" ? attr_options[attr].iNow / 100 : attr_options[attr].iNow + "px";
51             }
52         }
53     } , 30)
54 }

 

上一篇:List接口中的常用方法


下一篇:JavaScript 获取 dom 元素的原生方法