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。否则只会删除最后一个ele109  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 // 可能会不传callback44 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 }

 

相关文章