css样式
/*给box添加样式*/
.box{width:1000px;height:500px;background:black;margin:20px auto;cursor:pointer;position:relative;overflow: hidden}
/*为烟花上升过程中的元素添加样式*/
.box .fire{width:10px;height:10px;position:absolute;bottom:0;}
/*为将来烟花炸开的小元素添加样式*/
.box .s_fire{width:10px;height:10px;position:absolute;border-radius:50%;}
网页结构
//设置一个div模拟夜空,将来点击夜空的时候,烟花从鼠标下方升起,到达点击位置炸开
<div class="box"></div>
JavaScript代码
class Fire{ //利用ES6新增的class构造一个函数,用来模拟烟花上升过程
constructor(pos){
this.cont=document.querySelector(".box"); //选择元素
this.x=pos.x; //获取鼠标点击的位置
this.y=pos.y;
}
create(){ //创建create方法,用来给页面添加元素(烟花上升过程的元素)
this.f=document.createElement("div");
this.f.style.background=randomColor();
this.f.className="fire";
this.cont.appendChild(this.f);
this.f.style.left=this.x+"px"; //设置烟花初始位置
this.move(); //调用move方法运动
}
move(){ //创建move方法,模拟烟花上升的过程
move(this.f,{top:this.y},()=>{ //调用全局的move函数
this.f.remove();
var sum=random(20,30); //随机生成炸开的小元素个数
for(var i=0;i<sum;i++){
var sf=new SmallFire({x:this.x,
y:this.y,
cont:this.cont
}); //创建炸开的小烟花实例,将鼠标点击获取到的位置传到实例中
sf.create(); //执行创建小烟花的方法
}
});
}
}
class SmallFire{ //构造一个SmallFire函数,模拟烟花炸开效果
constructor(obj){
this.x=obj.x;
this.y=obj.y;
this.cont=obj.cont;
}
create(){ //创建小烟花的方法
this.f=document.createElement("div");
this.f.style.background=randomColor();
this.f.className="s_fire";
this.cont.appendChild(this.f);
this.f.style.left=this.x+"px"; //设置小烟花的初始位置
this.f.style.top=this.y+"px";
this.move(); //执行move方法,小烟花开始运动
}
move(){
var speedX=random(-10,10); //随机生成一个数字,表示烟花每一次的运动的距离
var speedY=random(-10,10);
this.f.t=setInterval(()=>{ //开启一个计时器,实现烟花的加速效果
if(this.f.offsetTop>this.cont.offsetHight){
clearInterval(this.f.t); //如果烟花超出了背景,清除计时器,并删除对应的小烟花
this.f.remove();
}else{
//如果没有超出,根据随机生成的距离移动
this.f.style.left=this.f.offsetLeft+speedX+"px";
//在移动过程中,将垂直方向的值不断增大,形成重力加速效果
this.f.style.top=this.f.offsetTop+speedY++ +"px";
}
},30)
}
}
var ocont=document.querySelector(".box");
ocont.onclick=function(eve){ //给夜空添加点击事件
var e=eve||window.event;
var x=e.pageX-ocont.offsetLeft; //获取鼠标点击是,相对于夜空的位置
var y=e.pageY-ocont.offsetTop;
var f=new Fire({x:x,y:y}); //将获取到的位置传给Fire函数
f.create(); //执行Fire函数中的creat方法,创建上升烟花的元素
}
function random(a,b){ //封装一个随机数函数,在随机生成颜色的函数中调用
return Math.round(Math.random()*(a-b)+b);
}
function randomColor(){ //封装一个随机颜色的函数
return `rgb(${random(0,255)},${random(0,255)},${random(0,255)})`;
}
function move(ele,obj,cb){ //封装一个move方法,实现缓冲运动效果
clearInterval(ele.t);
ele.t = setInterval(() => {
// 假设状态为:可以清除计时器
var i = true;
// 因为在计时器中才开始使用到对象中的信息,所以在计时器中遍历
// 并提前换来的属性和目标变量
for(var attr in obj){
var iNow = parseInt(getStyle(ele,attr));
}
let speed = (obj[attr] - iNow)/10;
speed = speed < 0 ? Math.floor(speed) : Math.ceil(speed);
if(iNow !== obj[attr]){
i = false;
}
ele.style[attr] = iNow + speed + "px";
}
// 如果每次计时器执行结束,所有属性都执行了一遍之后,状态还是true,表示,没有被改成false,如果没有被改成false,表示没有属性没到终点,那么状态还是false就不清除
if(i){
clearInterval(ele.t);
// 用户决定在动画结束时要执行的功能,万一用户没传参,做个默认判断
cb && cb();
}
}, 30);
}
function getStyle(ele,attr){ //用来获取页面元素的属性
if(ele.currentStyle){
return ele.currentStyle[attr];
}else{
return getComputedStyle(ele,false)[attr];
}
}