用canvas整个烟花效果

闲来无事,想着随便捣鼓一点东西玩玩
说说思路:

一 需要一个粒子类

模拟每一个烟花粒子,粒子有横坐标,纵坐标,半径,速度,颜色等属性,以及绘制的方法。 颜色这里我加了个初始化的方法,加了透明度的处理。代码如下:


// 粒子类
import Explode from "./explode.js";class Particle {constructor(ctx, x, y, radius = 5) {this.ctx = ctx;this.radius = radius;this.x = x;this.y = y;this.rgb = null;this.angle = 0;}// 初始化颜色initColor({ r, g, b }) {this.rgb = { r, g, b };this.color = "rgba(" + r + ", " + g + ", " + b + ", " + 1 + ")";}setColorAlpha(alpha) {this.color ="rgba(" +this.rgb.r +", " +this.rgb.g +", " +this.rgb.b +", " +1 +")";}paint() {this.ctx.beginPath();this.ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);this.ctx.fillStyle = this.color;this.ctx.fill();this.ctx.closePath();this.ctx.save();}del() {delete this;}
}export default Particle;

2 需要一个发射的类

其实一次发射就是一个粒子从底部到天空的过程,这里我把发射类继承了粒子类。代码如下:


import Particle from "./particle.js";
import { getRandomColorRGB } from "./utils.js";
import Explode from "./explode.js";// 随机生成一个发射角度 从-30度到30度
const getRandomAngle = () => {return Math.random() * (Math.PI / 3) - Math.PI / 6;
};// 生成一个随机speed
const getRandomSpeed = () => {return Math.random() * 10 + 15;
};export default class OneShot extends Particle {constructor(ctx, x, y) {super(ctx, x, y);this.speed = getRandomSpeed();this.initColor(getRandomColorRGB());this.paint();this.angle = getRandomAngle();this.explode = null;this.firstBoom = true;}launch() {if (this.speed <= 0) {// 如果速度小于等于0,就判断为到了爆炸阶段,进行爆炸的逻辑// 第一次进入爆炸逻辑,需生成一个爆炸实例if (this.explode) {this.explode.boom();} else {this.explode = new Explode(this.ctx, this.x, this.y, this.rgb);}// this.del();return;} else {// 发射阶段,发射角度是随机生成的(竖直方向往两边各偏移30度的范围内)this.x += this.speed * Math.sin(this.angle);this.y -= this.speed * Math.cos(this.angle);this.speed -= 0.4;this.paint();}}
}

3 需要一个爆炸类,模拟一次烟花发射到顶点时到爆炸效果。

每次到爆炸阶段,都可以往数组中添加num个粒子,起点一致往四周散开。还需要考虑到真实情况中的引力加速度。代码如下:


// 随机生成20-30个粒子,给不同的初始速度
import Particle from "./particle.js";// 随机生成一个发射角度 从0度到360度
const getRandomAngle = () => {return Math.random() * (Math.PI * 2);
};// 生成一个随机半径
const getRandomRadius = () => {return Math.random() * 3;
};// 生成一个随机speed
const getRandomSpeed = () => {return Math.random() + 1;
};export default class Explode {constructor(ctx, x, y, colorRGB, num = 30) {this.ctx = ctx;this.x = x;this.y = y;this.list = [];this.colorRGB = colorRGB;// 爆炸数量this.num = num;this.init();}init() {for (let i = 0; i < this.num; i++) {let p = new Particle(this.ctx, this.x, this.y, getRandomRadius());p.angle = getRandomAngle();p.initColor(this.colorRGB);p.speed = getRandomSpeed();this.list.push(p);}}boom() {// 爆炸阶段粒子移动逻辑,由爆炸中心往四周散开,角度随机从0-2*PIif (this.list.length === 0) return;for (let i = 0; i < this.list.length; i++) {const cur = this.list[i];cur.x += cur.speed * Math.sin(cur.angle);cur.y = cur.y + 0.2 - cur.speed * Math.cos(cur.angle);cur.paint();cur.speed -= 0.01;if (cur.speed < 0) {this.list.splice(i, 1);}}}
}

最后,再贴出index,html的代码:

<!--* @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git* @Date: 2024-02-01 15:13:28* @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git* @LastEditTime: 2024-05-28 21:32:51* @FilePath: /practice/index.html* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<!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>*{padding: 0;margin: 0;box-sizing: border-box;}body {width: 100vw;height: 100vh;background-color: black;}.firework {width: 2px;height: 2px;background-color: red;position: absolute;}#myCanvas {width: 100%;height: 100%;}.bot {width: 100px;height: 40px;background: lightcoral;position: absolute;bottom: 0;left: 50%;margin-left: -50px;}</style>
</head><body><canvas id="myCanvas" width="100px"></canvas><div class="bot"></div>
</body>
<script src="./main.js" type="module"></script></html>

当然,主方法一定要贴出来:


import oneShot from "./oneShot.js";// 获取 canvas 元素
const canvas = document.getElementById("myCanvas");
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
const ctx = canvas.getContext("2d");
window.W = canvas.width;
window.H = canvas.height;const startX = canvas.width / 2;
const startY = canvas.height - 40 - 5;const pList = [];
// 生成烟花粒子
for (let i = 0; i < 20; i++) {let p = new oneShot(ctx, startX, startY);pList.push(p);
}// 主进程方法
let timer;function main() {// ctx.clearRect(0, 0, W, H);pList.forEach((p) => p.launch());// 这里每次都绘制一个蒙层,来模拟拖尾的效果ctx.beginPath();ctx.fillStyle = "rgba(0,0,0,0.1)";ctx.fillRect(0, 0, W, H);ctx.closePath();ctx.save();timer = requestAnimationFrame(main);
}requestAnimationFrame(main);

ok,废话不多说,看看效果:

烟花-canvas

老表,学废了没?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/848565.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python读取字节数组

读取和处理bytearray中的值 # 输出&#xff1a;Combined 16-bit value: 1234 python-can发送和接收CAN报文 import can # 创建一个CAN总线对象&#xff08;这取决于你的硬件和驱动程序&#xff09; bus can.interface.Bus(channelcan0, bustypesocketcan) # 定义一个CAN…

【设计模式】JAVA Design Patterns——Proxy(代理模式)

&#x1f50d;目的 为另一个对象提供代理或占位符以控制对其的访问。 &#x1f50d;解释 真实世界例子 想象有一个塔&#xff0c;当地的巫师去那里学习他们的法术。象牙塔只能够通过代理来进入以此来保证只有首先3个巫师才能进入。这里的代理就代表的塔的功能并添加访问控制。 …

Web网站攻击技术

文章目录 Web应用体系结构脆弱性分析HTTP协议安全问题Cookie的安全问题 常见Web应用攻击及防范SQL注入攻击及防范SQL注入原理 防御注入漏洞跨站脚本(XSS)攻击及防范跨站脚本(XSS)攻击原理 跨站脚本攻击类型储存式XSS反射式XSSDOM式XSS Cookie欺骗及防范CSRF攻击及防范防御CSRF攻…

【数据结构】排序(直接插入、折半插入、希尔排序、快排、冒泡、选择、堆排序、归并排序、基数排序)

目录 排序一、插入排序1.直接插入排序2.折半插入排序3.希尔排序 二、交换排序1.快速排序2.冒泡排序 三、选择排序1. 简单选择排序2. 堆排序3. 树排序 四、归并排序(2-路归并排序)五、基数排序1. 桶排序&#xff08;适合元素关键字值集合并不大&#xff09;2. 基数排序基数排序的…

SpringCloud 服务调用 spring-cloud-starter-openfeign

spring-cloud-starter-openfeign 是 Spring Cloud 中的一个组件&#xff0c;用于在微服务架构中声明式地调用其他服务。它基于 Netflix 的 Feign 客户端进行了封装和增强&#xff0c;使其与 Spring Cloud 生态更好地集成。 1. Feign Feign 是一个声明式的 Web Service 客户端…

大功率回馈式负载:行业竞争态势

随着科技的不断发展&#xff0c;大功率回馈式负载在各个行业中的应用越来越广泛。大功率回馈式负载是一种能够将电能回馈到电网的设备&#xff0c;具有节能、环保、高效等优点。然而&#xff0c;随着市场竞争的加剧&#xff0c;大功率回馈式负载行业也面临着诸多挑战。 首先&am…

【HashMap】链表和红黑树互相转换的几种情况和数组的扩容机制

在Java的HashMap实现中&#xff0c;链表转换为红黑树的条件包括链表长度和HashMap的容量&#xff08;桶数组大小&#xff09;。具体规则如下&#xff1a; 链表长度阈值&#xff1a;当单个桶中的链表长度达到8时&#xff0c;该链表会被转换为红黑树。最小树化容量&#xff1a;H…

第二证券:A股重磅调整!富时中国A50指数将纳入中远海控中国中车

重要的音讯有哪些 A股&#xff0c;重磅调整&#xff01; 6月5日&#xff0c;富时罗素宣布对富时我国50指数、富时我国A50指数、富时我国A150指数、富时我国A200指数、富时我国A400指数的季度审阅变更。该变更将于2024年6月21日星期五收盘后&#xff08;即2024年6月24日星期一…

055、Python 关于全局变量和局部变量

定义&#xff1a; 全局变量&#xff1a;在函数外部定义的变量&#xff0c;可以在整个程序中访问。 局部变量&#xff1a;在函数内部定义的变量&#xff0c;只能在其定义的函数内部访问。 作用域优先级&#xff1a; 在 Python 中&#xff0c;作用域的查找顺序是&#xff1a;…

【Linux之·readelf工具·二进制程序处理工具】

系列文章目录 文章目录 前言一、使用readelf工具查看程序代码变量的内存空间布局情况1.1 源程序与程序的映射1.2 程序到进程的映射 二、readelf指令2.1 节头信息2.2符号表段中的项 总结 前言 在现代软件开发中&#xff0c;了解和理解可执行文件和共享库的结构变得越来越重要。而…

免费,C++蓝桥杯比赛历年真题--第14届蓝桥杯省赛真题(含答案解析和代码)

C蓝桥杯比赛历年真题–第14届蓝桥杯省赛真题 一、选择题 答案&#xff1a;A 解析&#xff1a; C中 bool 类型与 char 类型一样&#xff0c;都需要1 byte。一些其他类型的占用字节数:short:2 byte&#xff0c;int:4byte&#xff0c;long long:8 byte&#xff0c;double:8byte&…

探究MySQL中的“树”结构

1 引言 树高千丈,叶落求索 – 唐代杜牧 树结构在MySQL中常用于表示层次关系,如组织结构或分类体系。引入树结构可使数据之间建立父子关系,便于查询和管理。益处包括快速检索子节点、方便展示层次关系、支持递归查询等。 2 基础概念 2.1 名词解析 程序就像是一张有向图,你…

Linux操作系统:Spark在虚拟环境下的安装及部署

将Spark安装到指定目录 // 通过wget下载Spark安装包 $ wget https://d3kbcqa49mib13.cloudfront.net/spark-2.1.1-bin-hadoop2.7.tgz // 将spark解压到安装目录 $ tar –zxvf spark-2.1.1-bin-hadoop2.7.tgz –C /usr/local/ // 重命名 $ mv /usr/local/spark-2.1.1-bin-hado…

面试 Redis 八股文十问十答第三期

面试 Redis 八股文十问十答第三期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01;关注专栏后就能收到持续更新&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1&#xff09;redis 的 lua 脚本用过吗&…

前端怎么debugger排查线上问题

前端怎么debugger排查线上问题 1.问题背景2.问题详细说明3.处理方案a.开发环境怎么找&#xff0c;步骤一样的&#xff1a;b.生产环境怎么找&#xff0c;步骤一样的&#xff1a;还有一种情况就是你的子盒子是使用csshover父盒子出来的&#xff0c; 4.demo地址&#xff1a; 1.问题…

OOP 下一个排列(函数模板)

题目描述 输入一个序列&#xff0c;输出其下一个字典序的排列 如&#xff1a;输入1 2 3&#xff0c; 下一个为1 3 2&#xff0c; 下一个为2 1 3&#xff0c; 下一个为2 3 1&#xff0c; 下一个为3 1 2&#xff0c; 下一个为3 2 1&#xff08;最大的字典序排列&#xff0…

C++基础-编程练习题和答案(数组2)

文章目录 前言一、植树二、校门外的树三、排除第一个异形基因四、比身高五、supercell做核酸 前言 在C中&#xff0c;数组是一种数据结构&#xff0c;它允许在内存中连续存储相同类型的元素。数组是静态的&#xff0c;这意味着它们在编译时必须指定大小&#xff0c;并且在程序…

java版MES系统全套源码,支持 SaaS 多租户,管理后台的 Vue3 版本采用 :vue-element-plus-admin

MES生产制造执行系统源码&#xff0c;有演示&#xff0c;自主研发&#xff0c;多个项目应用案例&#xff0c;成熟稳定。支持二次开发&#xff0c;商业授权后可商用。 MES系统是面向制造企业车间执行层的生产信息化管理系统&#xff0c;能实时监控生产过程、管理制造数据、优化生…

惊呆了!六西格玛培训竟然这么强大!——张驰咨询

六西格玛&#xff0c;这个在业界久负盛名的管理理念&#xff0c;它的魅力太强大了。曾听闻它能帮助企业和个人提升竞争力&#xff0c;但当真正走进这个培训体系时&#xff0c;会发现它的影响力远超你的想象。 在六西格玛的指导下&#xff0c;企业实现了显著的转变。之前那些看…

vue使用html2canvas截图下载时,存在svg或者img或者特殊字体时截图不全的解决办法

使用html2canvas进行div截图时&#xff0c;存在svg和img的解决办法 写在前面&#xff1a;vue使用html2canvas截图时&#xff0c;存在svg或者img或者特殊字体时截图时空白&#xff0c;或者不全解决办法如下第一步&#xff0c;svg或者img先转base64&#xff08;如果是特殊字体&am…