html代码部分

<!DOCTYPE html>
<!--
* @Descripttion:
* @version:
* @Author: 小小荧
* @Date: 2020-03-18 19:15:15
* @LastEditors: 小小荧
* @LastEditTime: 2020-03-18 20:14:28
-->
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<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: 10px;
height: 10px;
position: absolute;
bottom: 0;
}
</style>
</head> <body>
<div class="container"></div>
<script src="./js/animate.js"></script>
<script src="./js/utils.js"></script>
<script src="./js/index.js"></script>
<script>
let container_ele = document.querySelector(".container");
container_ele.addEventListener("click", function(evt){
var e = evt || event;
new FireWork(e.offsetX, e.offsetY, ".container");
})
</script>
</body> </html>

JS代码运动函数

/*
* @Descripttion:
* @version:
* @Author: 小小荧
* @Date: 2020-03-17 18:01:21
* @LastEditors: 小小荧
* @LastEditTime: 2020-03-18 19:14:55
*/
/**
* 多属性的动画函数
* @param {*} ele 需要运动的节点
* @param {*} attr_options 传入的是一个需要运动的属性包括运动的目标值,操作的节点属性
* @param {*} timefn 运动的形式,默认是缓冲运动
* @param {*} speed 运动的速度
*/
function animate(ele, attr_options, callback, timefn = "swing", speed = 5) { // 我们需要把传入的options处理成
/*
{“width : {
target : 200,
iNow : 100
}}这个形式
*/ for (var attr in attr_options) {
attr_options[attr] = {
target: attr === "opacity" ? parseInt(attr_options[attr] * 100) : attr_options[attr],
// 需要计算得到
iNow: attr === "opacity" ? parseInt(getComputedStyle(ele)[attr] * 100) : parseInt(getComputedStyle(ele)[attr])
}
} // 为了防止每个节点的定时器冲突,每次进入的时候我们需要先清理下节点的定时器
clearInterval(ele.timer);
// 然后再去设置定时器
ele.timer = setInterval(function () { // 因为是多属性运动,我们首先循环遍历每一个属性
for (var attr in attr_options) { var target = attr_options[attr].target; var iNow = attr_options[attr].iNow; // 计算speed 判断是不是缓冲运动
if (timefn === "swing") {
speed = (target - iNow) / 20;
// 为了防止速度无法达到一个整数
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
}
// 判断是不是匀速运动
else if (timefn === "liner") {
speed = attr_options[attr].iNow < attr_options[attr].target ? Math.abs(speed) : -Math.abs(speed);
} // 运动之中条件的判断
if (Math.abs(target - iNow) <= Math.abs(speed)) { if (attr === "opacity") {
ele.style[attr] = target / 100;
} else { ele.style[attr] = target + "px"; } // 每次一个属性运动完成之后我们就直接将它删除
delete attr_options[attr]; // 每次都去循环看一下还有没有属性需要操作
for (var num in attr_options) {
return false;
}
// 清理定时器 因为我们是一个定时器绑定多个属性操作所以我们需要保证所有的属性都完成之后我们才可以将定时器清除
clearInterval(ele.timer);
// 等结束之后我们需要判断这个回到函数是函数我们就回调
typeof callback === "function" ? callback() : "" } else {
attr_options[attr].iNow += speed;
if (attr === "opacity") {
ele.style[attr] = attr_options[attr].iNow / 100;
} else {
ele.style[attr] = attr_options[attr].iNow + "px";
}
}
} }, 30);
}

JS代码核心主业务代码

/*
* @Descripttion:
* @version:
* @Author: 小小荧
* @Date: 2020-03-18 19:16:48
* @LastEditors: 小小荧
* @LastEditTime: 2020-03-18 20:12:07
*/
class FireWork {
// 构造器
/**
*
* @param {*} x x轴坐标
* @param {*} y y轴坐标
* @param {*} seletor 选择器名
*/
constructor(x, y, seletor) {
// 父容器的节点
this.main = document.querySelector(seletor); this.init(x, y);
} /**
* 初始化方法
* @param {*} x x的坐标
* @param {*} y y的坐标
*/
init(x, y) { this.x = x;
this.y = y; // 创建的烟花的节点
this.ele = this.createFireWorkEle();
// 运动的最大left值
this.left_max = this.main.offsetWidth - this.ele.offsetWidth;
// 运动的最大的top值
this.top_max = this.main.offsetHeight - this.ele.offsetHeight; // 设置烟花的开始颜色
this.randomColor(this.ele);
// 烟花开始运动
this.fireworkUp(this.ele);
}
/**
* 创建烟花的元素
*/
createFireWorkEle() {
// 创建节点
let ele = document.createElement("div");
// 设置类名
ele.className = "fire";
// 在父容器追加节点
this.main.appendChild(ele);
return ele;
} /**
*
* 烟花运动的方法
* @param {*} ele 运动的这个烟花
*/
fireworkUp(ele) { // 设置left
ele.style.left = this.x + "px";
// 烟花向上的运动我们使用animate动画
animate(ele, {
top: this.y,
}, () => { // 等到这个烟花运动结束之后呢我们需要将这个烟花给删除了
ele.parentNode.removeChild(ele);
// 结束之后烟花开始爆炸
this.fireworkBlast(); }); } /**
* 烟花爆炸的方法
*/
fireworkBlast() {
// 我们设置爆炸的数量为20
for (let i = 0; i < 20; i++) {
// 我们需要重新创建烟花的元素
let ele = this.createFireWorkEle();
// 给元素设置随机背景颜色和left,top,圆角属性值
this.randomColor(ele); ele.style.left = this.x + "px"; ele.style.top = this.y + "px"; ele.style.borderRadius = "50%"; // 然后我们需要让这些元素开始运动,先获取随机坐标带你
animate(ele, this.randomPos(), () => {
// 删除烟花
ele.parentNode.removeChild(ele)
});
}
} /**
* 随机获取坐标点
*/
randomPos() {
return {
left: Math.round(Math.random() * this.left_max),
top: Math.round(Math.random() * this.top_max)
}
} /**
*
* 随机背景颜色
* @param {*} ele 小烟花的元素
*/
randomColor(ele) { return ele.style.backgroundColor = utils.randomColor();
} }

utils的随机生成颜色的函数

 let randomColor = function () {
let res = "#";
for (let i = 0; i < 6; i++) {
res += parseInt(Math.random() * 10).toString(16);
}
return res;
}

JS烟花案例的更多相关文章

  1. JS烟花案例优化版

    不明白为什么是烟花优化版本的先参考作者的烟花基础版本 烟花优化版本主要实在优化爆炸的范围和运动上做了优化,爆炸范围我们采用已圆的爆炸方式,以鼠标点击的位置为圆形爆炸的烟花效果 <!DOCTYPE ...

  2. 【Vue.js实战案例】- Vue.js递归组件实现组织架构树和选人功能

    大家好!先上图看看本次案例的整体效果. 浪奔,浪流,万里涛涛江水永不休.如果在jq时代来实这个功能简直有些噩梦了,但是自从前端思想发展到现在的以MVVM为主流的大背景下,来实现一个这样繁杂的功能简直不 ...

  3. js计算器案例

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>j ...

  4. 正則表達式--js使用案例

    前言:在前端页面使用中.遇到日期格式的验证.開始使用了一款表单控件验证.可是不兼容!!并且使用起来还受到非常大约束.所以就决定自己写原生js. 为了完毕日期格式的验证.第一步,当然是学会使用正則表達式 ...

  5. JS小案例:循环间隔重复变色

    在A.B.C三个区块中,有且仅有一个红色,要求红色每隔一秒即进入下一个区块,变色过程不断循环往复. 参考代码: <!DOCTYPE html> <html lang="zh ...

  6. JavaScript中的面向对象编程,详解原型对象及prototype,constructor,proto,内含面向对象编程详细案例(烟花案例)

    面向对象编程:   面向:以什么为主,基于什么模式 对象:由键值对组成,可以用来描述事物,存储数据的一种数据格式 编程:使用代码解决需求   面向过程编程:         按照我们分析好的步骤,按步 ...

  7. node.js(小案例)_实现学生信息增删改

    一.前言 本节内容主要对小案例做一个总结: 1.如何开始搭建小项目 2.路由设计 3.模块应用 4.项目源码以及实现过程github地址: 项目演示如下: 二.主要内容 1.项目的关键性js源码: 项 ...

  8. node.js小案例_留言板

    一.前言 通过这个案例复习: 1.node.js中模板引擎的使用 2.node.js中的页面跳转和重定向 二.主要内容 1.案列演示:  2.案列源码:https://github.com/45612 ...

  9. node.js 爬虫案例

    本案例是爬的一部小说,爬取并存在本地 使用了动态浏览器头部信息,和 动态ip代理, 这2个方式可以有效的伪装自己,不至于被反爬,然后拉黑,之前已有记录,浏览器头部信息,也记录的有, app.js im ...

随机推荐

  1. 探索 Redux4.0 版本迭代 论基础谈展望(对比 React context)

    Redux 在几天前(2018.04.18)发布了新版本,6 commits 被合入 master.从诞生起,到如今 4.0 版本,Redux 保持了使用层面的平滑过渡.同时前不久, React 也从 ...

  2. PYTHON程序设计实验

    Python程序设计实验报告一: 熟悉IDLE和在线编程平台 安徽工程大学 Python程序设计实验报告 班级 物流191 姓名 邹缕学号 3190505117成绩 ▁▁▁ 日期 2020.3.5 指 ...

  3. A. New Building for SIS Codeforce

    You are looking at the floor plan of the Summer Informatics School's new building. You were tasked w ...

  4. [poj1062][最短路]昂贵的聘礼

    (最近总是有想让我的小博客更加充实的冲动,遇见一个不平常的题就想写下来.今天这个题姑且算是同学推荐的好题,很有意思,志之) 题目 题面 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了, ...

  5. CSS 权重图

    关系图 图片出处我找不到了. 结论 权重从高到低排序 1. !important 2. style 3. #id 4. .class .child-class 5. .class1.class2 6. ...

  6. ggplot2练习

    图源于电力电子课本65页——电容滤波的单相不可控整流电路. f<-function(w,d) { l<-w/sqrt(w^2+1)*exp(-atan(w)/w)*exp(-d/w) r& ...

  7. 事务特性,事务的隔离级别以及spring中定义的事务传播行为

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  8. C++中的内存分配

    C++提供下面两种方法分配和释放未构造的原始内存 (1)allocator 类,它提供可感知类型的内存分配 (2)标准库中的 operator new 和 operator delete,它们分配和释 ...

  9. Netty之缓冲区ByteBuf解读(二)

    上篇介绍了 ByteBuf 的简单读写操作以及读写指针的基本介绍,本文继续对 ByteBuf 的基本操作进行解读. 读写指针回滚 这里的 demo 例子还是使用上节使用的. ByteBuf buf = ...

  10. 菜鸟对java和Go的理解

    1.go对比java go通过结构体嵌套+接口实现类似面向对象中的继承和多态.个人认为尤其是go的接口抓住了多态的本质.而Go提倡的面向接口的思想也可能使得架构上更加解耦. 2.关于Go不要通过共享内 ...