css动画烟花秀__烟花效果

embedded/2024/10/25 4:52:00/

先看效果

CSS烟花秀

这是一个在HTML5页面,实现烟花效果的例子

以下为实现代码

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>烟花</title>
</head>
<style>body {margin: 0;padding: 0;overflow: hidden;}.canvasBox {width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;}canvas {border: 1px solid;background-color: #ccc;}
</style><body>
<div class="canvasBox"><canvas id="canvas"></canvas>
</div>
<audio id="background-music" src="yanhua.mp3"  preload="auto" autoplay loop></audio>
</body></html>
<script src="test.js"></script>
<script>const canvas = document.getElementById('canvas')const canvasWidth = document.documentElement.clientWidth || document.body.clientWidthconst canvasHeight = document.documentElement.clientHeight || document.body.clientHeightconst ratio = Math.max(window.devicePixelRatio, 2)canvas.width = canvasWidth * ratiocanvas.height = canvasHeight * ratiocanvas.style.width = canvasWidth + 'px'canvas.style.height = canvasHeight + 'px'const ctx = canvas.getContext('2d')ctx.scale(ratio, ratio)const getRandom = (min, max) => {return Math.random() * (max - min) + min}const drawCircle = ({ opacity = 1, x, y, radius, color }) => {ctx.save()ctx.globalAlpha = opacityctx.beginPath()ctx.arc(x, y, radius, 0, Math.PI * 2)ctx.fillStyle = colorctx.fill()ctx.restore()}const deleteFromList = (list, target) => {const index = list.findIndex(item => {return item === target})list.splice(index, 1)}// 动画循环// 烟花列表const fireworkList = []const draw = () => {// 使用半透明清空画布,形成拖尾效果ctx.fillStyle = 'rgba(0,0,0,0.1)'ctx.fillRect(0, 0, canvasWidth, canvasHeight)ctx.save()// 修改坐标系ctx.translate(0, canvasHeight)ctx.scale(1, -1)const list = [...fireworkList]list.forEach(firework => {firework.update()if (firework.isEnd()) {deleteFromList(fireworkList, firework)}})ctx.restore()requestAnimationFrame(draw)}draw()// 烟花颜色列表const createFireworkColor = () => {const colorList = ['#ff0043','#14fc56','#1e7fff','#e60aff','#ffbf36','#ffffff']return colorList[Math.floor(Math.random() * colorList.length)]}// 发射烟花//canvas.addEventListener('click', () => {setInterval(function () {const firework = new Firework({color: createFireworkColor()})fireworkList.push(firework)firework.launch()}, 1000);//})</script>

 其中引用的一个test.js文件 如下:

// 爆炸碎片类
class ExplosiveDebris {constructor(opt) {this.firework = opt.fireworkthis.x = opt.xthis.y = opt.ythis.color = Math.random() > 0.2 ? opt.color : '#fff'this.radius = opt.radius || 2this.angle = getRandom(0, 2 * Math.PI)this.speed = opt.speed || getRandom(0.1, 4)this.vx = Math.cos(this.angle) * this.speedthis.vy = Math.sin(this.angle) * this.speedthis.g = opt.g || 0.98this.time = getRandom(0.5, 1)this.startTime = 0// 痕迹碎片数量this.debrisCount = opt.debrisCount || 3// 是否要进行二次爆炸this.secondBurst = opt.secondBurst || false}start() {this.startTime = Date.now()}update() {const duration = (Date.now() - this.startTime) / 1000const vy = this.vy - this.g * durationthis.x += this.vxthis.y += vyconst progress = duration / this.timelet opacity = progress > 0.7 ? 1 - 1 * progress : 1if (opacity < 0) opacity = 0drawCircle({x: this.x,y: this.y,color: this.color,radius: this.radius,opacity: opacity})// 添加痕迹碎片if (this.debrisCount > 0 && Math.random() > 0.8) {this.debrisCount--this.firework.addDebris({x: this.x + getRandom(-2, 2),y: this.y + getRandom(-2, 2),color: this.color,radius: 0.5,g: 0.1})}return {x: this.x,y: this.y,isEnd: progress >= 1}}
}// 爆炸器类
class Explosive {constructor(opt) {this.firework = opt.fireworkthis.x = opt.xthis.y = opt.ythis.color = opt.color// 爆炸碎片列表this.debrisList = []// 爆炸碎片数量this.debrisNum = opt.debrisNum || getRandom(10, 2000)// 是否要二次爆炸this.secondBurst = opt.secondBurst || this.debrisNum <= 100//是否是第一次爆炸this.isFirstBurst = true}start(debrisNum, opt = {}) {const num = debrisNum || this.debrisNumopt.x = opt.x || this.xopt.y = opt.y || this.yopt.secondBurst = this.secondBurst && this.isFirstBurstfor (let i = 0; i < num; i++) {const explosiveDebris = new ExplosiveDebris({firework: this.firework,color: this.color,...opt})explosiveDebris.start()this.debrisList.push(explosiveDebris)}this.isFirstBurst = false}update() {const list = [...this.debrisList]list.forEach(debris => {const res = debris.update()if (res.isEnd) {deleteFromList(this.debrisList, debris)// 二次爆炸if (debris.secondBurst) {this.start(5, {x: res.x,y: res.y,speed: 1})}}})return {isEnd: list.length <= 0}}
}// 痕迹碎片类
class Debris {constructor(opt = {}) {// 颜色this.color = opt.color || '#fff'// 透明度this.opacity = getRandom(0.1, 0.5)// 半径this.radius = opt.radius || 1// 存在时间this.time = getRandom(0.5, 1)// 重力,px/s2this.g = opt.g || 0.98// 位置this.x = opt.xthis.y = opt.y// 创建的时间this.startTime = 0}start() {this.startTime = Date.now()}update() {const duration = (Date.now() - this.startTime) / 1000this.y -= this.g * durationdrawCircle({opacity: this.opacity,x: this.x,y: this.y,radius: this.radius,color: this.color})return {x: this.x,y: this.y,isEnd: duration > this.time}}
}// 发射器类
class Launcher {constructor(opt = {}) {// 烟花实例this.firework = opt.firework// 颜色this.color = opt.color// 初始位置this.x = opt.x || canvasWidth * getRandom(0.2, 0.8)this.y = opt.y || 0// 目标位置this.ty = canvasHeight * getRandom(0.6, 0.8)// 半径this.radius = opt.radius || getRandom(2, 5)// 发射的持续时间this.duration = opt.duration || getRandom(2000, 3500)// 发射时的时间this.startTime = 0}start() {this.startTime = Date.now()}easeOutCubic(t, b, c, d) {return c * ((t = t / d - 1) * t * t + 1) + b}update() {const x = this.xlet y = this.easeOutCubic(Date.now() - this.startTime,this.y,this.ty - this.y,this.duration)y = Math.min(y, this.ty)// 透明度变小let opacity = 1 - 1 * (y / this.ty)if (opacity < 0) opacity = 0this.draw(x, y, opacity)// 添加痕迹碎片if (Math.random() > 0.7 && opacity >= 0.1) {this.firework.addDebris({x: x + getRandom(-2, 2), // x坐标添加一段随机量y})}return {x,y,isEnd: y >= this.ty //返回true代表发射结束}}draw(x, y, opacity) {// 外圆,烟花的颜色drawCircle({opacity: opacity,x: x,y: y,radius: this.radius,color: this.color})// 内圆,白色drawCircle({opacity: opacity,x: x,y: y,radius: this.radius / 2,color: '#fff'})}
}// 烟花类
class Firework {constructor(opt = {}) {// 颜色this.color = opt.color || tinycolor.random().toHexString()// 发射器this.launcher = null// 爆炸器this.explosive = null// 烟花状态:waiting(等待发射)、launching(发射中)、bursting(爆炸中)、end(烟花结束)this.status = 'waiting'// 痕迹碎片列表this.debrisList = []}// 发射launch() {this.launcher = new Launcher({firework: this,color: this.color})this.launcher.start()this.status = 'launching'}// 爆炸burst({ x, y }) {this.explosive = new Explosive({firework: this,x,y,color: this.color})this.explosive.start()}// 更新update() {if (this.status === 'launching') {const res = this.launcher.update()if (res.isEnd) {this.status = 'bursting'this.burst(res)}} else if (this.status === 'bursting') {const res = this.explosive.update()if (res.isEnd) {this.status = 'end'}}// 更新痕迹碎片this.updateDebris()}// 添加痕迹碎片addDebris(opt = {}) {const debris = new Debris({...opt,color: opt.color || this.color})debris.start()this.debrisList.push(debris)}// 更新痕迹碎片updateDebris() {const list = [...this.debrisList]list.forEach(debris => {const res = debris.update()if (res.isEnd) {deleteFromList(this.debrisList, debris)}})}isEnd() {return this.status === 'end'}
}

一个音频文件为 yanhua.mp3


http://www.ppmy.cn/embedded/132242.html

相关文章

多模态大语言模型(MLLM)-Blip3/xGen-MM

论文链接&#xff1a;https://www.arxiv.org/abs/2408.08872 代码链接&#xff1a;https://github.com/salesforce/LAVIS/tree/xgen-mm 本次解读xGen-MM (BLIP-3): A Family of Open Large Multimodal Models 可以看作是 [1] Blip: Bootstrapping language-image pre-training…

太速科技-426-基于XC7Z100+TMS320C6678的图像处理板卡

基于XC7Z100TMS320C6678的图像处理板卡 一、板卡概述 板卡基于独立的结构&#xff0c;实现ZYNQ XC7Z100DSP TMS320C6678的多路图像输入输出接口的综合图像处理&#xff0c;包含1路Camera link输入输出、1路HD-SDI输入输出、1路复合视频输入输出、2路光纤等视频接口&#xff0c;…

CZX前端秘籍2

vue生命周期&#xff08; 组件从创建到销毁的过程就是它的生命周期&#xff09; 创建前 beforeCreat&#xff08; 在这个阶段属性和方法都不能使用&#xff09; 创建时 created&#xff08; 这里时实例创建完成之后&#xff0c; 在这里完成了数据监测&#xff0c; 可以使用数…

Keepalived+Mysql实现高可用配置总结

通过本文,大家将学习到以下相关知识内容: 1、什么是高可用服务 2、Keepalived简介 3、Keepalived常见应用场景 4、Keepalived高可用故障切换原理介绍 5、VRRP协议介绍 6、配置实现Keepalived监控Mysql 7、Keepalived配置文件介绍 8、Keepalived常见问题列举 一、什么…

Lesson10---list

Lesson10—list 第10章 c的list的使用和实现 文章目录 Lesson10---list前言一、list的初始化二、list的遍历1.迭代器2.范围for 三、list常用的内置函数1.sort&#xff08;慎用&#xff09;2.unique3.reverse4.merge5.splice 四、模拟实现1.基本框架2.构造函数3.push_back4. 遍…

微调大模型-2-Qwen基座模型使用

下载Qwen源码 Qwen作为中文支持非常nice的模型&#xff0c;很适合用于LLM学习。在云服务器里clone Qwen工程。 git clone https://github.com/QwenLM/Qwen2.5.git原始模型使用主要基于cli_demo.py-命令行调用&#xff0c;web_demo.py-网页调用。 预览这两个文件时&#xff0c…

Android音视频 MediaCodec框架-创建流程(3)

Android音视频 MediaCodec框架-创建流程 简述 之前我们介绍并且演示了MediaCodec的接口使用方法&#xff0c;我们这一节来看一下MediaCodec进行编解码的创建流程。 java层的MediaCodec只是提供接口&#xff0c;实际的逻辑是通过jni层实现的&#xff0c;java层的MediaCodec通过…

1024程序员节- AI智能时代,码出未来

在 1024 程序员节这个特殊的日子里&#xff0c;探讨了 AI 技术在不同领域的应用与发展。上海和深圳作为科技创新的前沿阵地&#xff0c;相关活动中的演讲内容更是聚焦了 AI 技术的核心要点&#xff0c;为我们展示了 AI 时代的新趋势和新机遇。 一、AI 技术的发展历程与背景 AI…