心形煙花

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .container{ width: 80%; height: 600px; border: 2px solid red; background: #000; margin:20px auto; cursor: pointer; position: relative; left: 0; top: 0; overflow: hidden; } .fire{ width: 6px; height:6px; position: absolute; animation: fireBug 3s infinite; bottom: 0; } @keyframes fireBug{ 0% {opacity:1;} 50% {opacity:0.2;} 100% {opacity:1;} } </style> </head> <body> <div class="container"> </div> <script src="./animate-opacity.js"></script> </body> <script> class FireWork{ constructor(options){ //單例模式 如果 FireWork上已經有選擇好的元素了,那么我們就不需要重復進行選擇了 if(FireWork.main && FireWork.main.selector === options.main){ //已經經歷過元素選擇了,所以直接賦值 this.main = FireWork.main.ele; }else{ //還沒有進行元素選擇; //將需要獲取的DOM放入對象中 , 進行判斷的也放入對象中 FireWork.main = { ele : document.querySelector(options.main), selector : options.main } this.main = FireWork.main.ele; } //獲取煙花爆炸的方式,並放入原型中 this.blast_type = options.blast_type; //將傳入的需要創建的子元素tagName放入原型中 this.ele_tagName = options.children; //將獲取傳入的鼠標點擊位置 this.x = options.x; this.y = options.y; //調用初始化方法 this.init() } init(){ //創建DIV this.ele = this.createFireWork() //設置邊界 this.left_max = this.main.offsetWidth - this.ele.offsetWidth; this.top_max = this.main.offsetHeight - this.ele.offsetHeight; //調用煙花上升的方法 this.fireWorkUp(this.ele) } //創建DIV createFireWork(){ var ele = document.createElement(this.ele_tagName) ele.className = "fire" //調用方法設置隨機顏色 this.randomColor(ele); return this.main.appendChild(ele) } //設置煙花上升 fireWorkUp(ele){ //設置煙花上升的橫坐標 ele.style.left = this.x + "px"; //調用封裝好的運動JS , 設置元素想上運動 animate(ele , {top : this.y} , function(){ //煙花到達指定地點之后消失 ele.remove(); //調用煙花的爆炸效果 this.fireWorkBlast() }.bind(this)) } //煙花爆炸效果 fireWorkBlast(){ //設置煙花爆炸之后散發的光點個數 for(var i = 0; i < 100; i++){ //創建對應的DIV var ele = this.createFireWork() //設置隨機顏色 this.randomColor(ele); //設置隨機位置 ele.style.left = this.x + "px"; ele.style.top = this.y + "px"; ele.style.borderRadius = "50%"; //判斷爆炸之后的形狀 switch(this.blast_type){ //爆炸之后成圓形 case "circle": //設置散發之后成一個圓形 animate(ele ,this.circleBlast( i , 20),function(ele){ //運動完成之后消失 ele.remove() }.bind(this , ele)); break; //爆炸之后成心形 case "heart": //設置散發之后成一個愛心 animate(ele , this.heartBlast(i),function(ele){ ele.remove() }.bind(this , ele)) break //爆炸之后隨機運動 default : animate(ele , this.randomPosition(),function(ele){ ele.remove() }.bind(this , ele)) break } } } //設置隨機顏色 randomColor(ele){ return ele.style.backgroundColor = "#" + parseInt(parseInt("ffffff" , 16) * Math.random()).toString(16).padStart(6,0); } //散發隨機位置 randomPosition(){ return { left : parseInt(Math.random() * (this.left_max + 1)), top : parseInt(Math.random() * (this.top_max + 1)) } } //散發形成一個圓形 circleBlast(index , all){ var r = 100; var reg = (360 / all) * index; var deg = Math.PI / 180 * reg; return { left : parseInt(r * Math.cos( deg )) + this.x, top : parseInt(r * Math.sin( deg )) + this.y } } //散發成一個愛心 heartBlast(i){ var r = 60; var m = i; var n = -r * (((Math.sin(i) * Math.sqrt(Math.abs(Math.cos(i)))) / (Math.sin(i) + 1.4)) - 2 * Math.sin(i) + 2); return { left : n * Math.cos(m) + this.x, top : n * Math.sin(m) + this.y } } } var ele_con = document.querySelector(".container") ele_con.addEventListener("click" , function(evt ){ var e = evt || event; new FireWork({ main : ".container", children : "div", x : e.offsetX , y : e.offsetY, blast_type : "heart" //設置煙花爆炸之后的形狀 }); }) </script> </html>
引入的的js文件
function animate( ele , attr_options , callback ){ for(var attr in attr_options){ // console.log(attr_options , attr_options[attr]) attr_options[attr] = { // 目標點 : 傳入的數據; target : attr === "opacity" ? attr_options[attr] * 100 : attr_options[attr], // 元素當前的屬性值 ; iNow : attr === "opacity" ? parseInt( getComputedStyle(ele)[attr] * 100 ) : parseInt( getComputedStyle(ele)[attr]) } // console.log(attr_options , attr_options.width) } // 關閉開啟定時器; clearInterval( ele.timer ); ele.timer = setInterval( function(){ // 1. 獲取速度; width : height : for(var attr in attr_options){ // attr : width | height; var item = attr_options[attr]; // console.log(item , attr); var target = item.target; var iNow = item.iNow; // 運動所必須的值我們都有了; // 計算速度; var speed = (target - iNow) / 20; // 速度取整; speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); // 終止條件 : if( Math.abs( target - iNow) <= Math.abs(speed) ){ // 終止定時器 ; // 送他一把; // clearInterval( ele.timer ); // ele.style[attr] = target + "px"; // 終止條件不可靠,因為目標的不一致會讓運動次數執行不同,有可能提前關閉定時器; ele.style[attr] = attr === "opacity" ? target / 100 : target + "px"; // 一條運動完成刪除對象里面的數據; delete attr_options[attr]; // 如果對象里面沒有屬性了,那么我們關閉定時器就可以了; for(var num in attr_options){ // 如果attr_options里面有屬性,那么此時我就不應該終止定時器; return false; } clearInterval(ele.timer); typeof callback === "function" ? callback() : ""; }else{ // 元素運動; // 因為 iNow 是一個臨時變量,所以不能再去操作iNow , 要去操作iNow 的數據源; // 多花點經歷理解這段代碼; attr_options[attr].iNow += speed; ele.style[attr] = attr === "opacity" ? attr_options[attr].iNow / 100 : attr_options[attr].iNow + "px"; } } } , 30) }
