基本效果如图:
这里的烟花特效 是配合鼠标点击去实现的 (你要是想绑定别的事件也可)
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 }