<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
</body>
<script src="./js/utils.js"></script>
<script>
// 烟花效果逻辑:
/*
创建夜空 - 创建div,放在body中,设置样式
给夜空绑定单击事件
记录鼠标的位置 - 使用事件对象的pageX pageY
创建小烟花 - 创建小div,设置样式,放在夜空中 - 设置left值是鼠标的pageX
烟花上升到鼠标位置 - 给小div添加动画效果 - top属性的动画 - pageY
在这个位置创建很多小div - 指定创建数量 - 循环创建 - 添加样式 - 放在夜空中
让每个小div都动画到一个随机位置 - 在夜空中获取一个随机坐标 - 设置小div动画到随机位置
到了随机位置以后,把小div删掉 - 动画结束后,清除定时器,删除小div - 夜空.removeChild(小div)
*/
function FireWorks(){
// 给对象添加属性 - 创建标签作为对象的属性
this.nightSky = document.createElement('div')
// 设置样式
this.setStyle(this.nightSky, {
width: '1000px',
height: '500px',
backgroundColor: '#000',
border: '10px solid #00f',
position: 'relative'
})
// 将夜空放在body中
document.body.appendChild(this.nightSky)
// 绑定事件
this.nightSky.onclick = () => {
var e = window.event;
var x = e.pageX;
var y = e.pageY;
// 调用创建小烟花的方法
this.createFire(x, y)
}
}
// 创建小烟花的方法
FireWorks.prototype.createFire = function(x, y){
// 创建小div
var fire = document.createElement('div')
// 设置样式
this.setStyle(fire, {
width: '10px',
height: '10px',
backgroundColor: this.getColor(),
left: x + 'px',
bottom: 0,
position: 'absolute'
})
// 将小烟花放在夜空中
this.nightSky.appendChild(fire)
// 让小烟花升空
this.toSky(x, y, fire)
}
// 小烟花升空的方法
FireWorks.prototype.toSky = function(x, y, fire){
// 调用工具库中的animate函数实现动画
animate(fire, {
top: y
}, () => {
// 将原来的一个小烟花删除
fire.parentElement.removeChild(fire)
// console.log(this);
// console.log('升空结束');
// 当前升空动画结束以后,创建30~50个小烟花
var num = this.getRandom(30, 50)
// console.log(num);
// 循环创建很多小div
for(let i=0;i<num;i++){
// 创建小div
var div = document.createElement('div')
// 设置样式
this.setStyle(div, {
width: '10px',
height: '10px',
backgroundColor: this.getColor(),
position: 'absolute',
left: x + 'px',
top: y + 'px',
borderRadius: '50%'
})
// 放在夜空中
this.nightSky.appendChild(div)
// 每个小烟花要炸开
this.boom(div)
}
})
}
// 炸开的方法
FireWorks.prototype.boom = function(ele){
// 让ele动画到一个随机位置
// 获取随机位置
var randomLeft = this.getRandom(this.nightSky.clientWidth - 10)
var randomTop = this.getRandom(this.nightSky.clientHeight - 10)
// 让ele开始动画
animate(ele, {
left: randomLeft,
top: randomTop
}, () => {
// console.log("动画结束了");
// 让夜空删掉ele
ele.parentElement.removeChild(ele)
})
}
// 获取随机颜色的方法
FireWorks.prototype.getColor = function(){
var color = '#'
for(var i=0;i<3;i++){
var hex = this.getRandom(256).toString(16)
hex = hex.length === 1 ? '0' + hex : hex;
color += hex
}
return color
}
// 获取随机数的方法
FireWorks.prototype.getRandom = function(a, b = 0){
var abs = Math.abs(a - b)
var min = Math.min(a, b)
return Math.floor(Math.random() * abs) + min
}
// 批量设置样式的方法
FireWorks.prototype.setStyle = function(ele, styleObj){
for(var key in styleObj){
ele.style[key] = styleObj[key]
}
}
var f = new FireWorks()
console.log(f);
</script>
</html>
/**
* 获取随机数的函数
* @param {number} a 代表范围的数字
* @param {number} b 代表范围的数字
* @return {number} 返回范围内的随机整数
*/
function getRandom(a, b){
return Math.floor(Math.random() * Math.abs(a - b)) + Math.min(a, b)
}
/**
* 获取16进制的随机颜色值
*/
function getColor(){
var color = '#'
for(var i=0;i<3;i++){
var hex = getRandom(0, 256).toString(16)
color += hex.length === 1 ? '0' + hex : hex;
}
return color
}
/**
* 批量设置样式的函数
* @param {node} ele 被设置样式的标签对象
* @param {object} styleObj 要设置的样式组成的键值对
*/
function setStyle(ele, styleObj){
for(var key in styleObj){
ele.style[key] = styleObj[key]
}
}
/**
* 进行动画的函数
* @param {node} ele 要进行动画的元素
* @param {object} obj 动画的属性和值组成的键值对
* @param {function} fn 动画结束后要执行的函数
*/
function animate(ele, obj, fn){
var k = 0
for(var key in obj){
k++
(function(key){
var currentStyle = getComputedStyle(ele)[key]
var target = obj[key]
if(key === 'opacity'){
currentStyle *= 100
target *= 100
}
currentStyle = parseInt(currentStyle)
var timerId = setInterval(function(){
var speed = (target - currentStyle) / 20
currentStyle += speed > 0 ? Math.ceil(speed) : Math.floor(speed)
if(key === 'opacity') ele.style[key] = currentStyle / 100
else ele.style[key] = currentStyle + 'px'
if(currentStyle === target){
clearInterval(timerId)
if(--k === 0) fn()
}
}, 20)
})(key)
}
}