程序员过圣诞 | 用HTML写出绽放的烟花

news/2024/5/19 3:20:46/文章来源:https://blog.csdn.net/CSDN_anhl/article/details/128437420

文章目录

    • 一、前言
    • 二、创意名
    • 三、效果展示
    • 四、烟花代码
    • 五、总结


一、前言

2022年圣诞节到来啦,圣诞节是基督教纪念耶稣诞生的重要节日。亦称耶稣圣诞节、主降生节,天主教亦称耶稣圣诞瞻礼。耶稣诞生的日期,《圣经》并无记载。公元336年罗马教会开始在12月25日过此节。12月25日原是罗马帝国规定的太阳神诞辰。有人认为选择这天庆祝圣诞,是因为基督教徒认为耶稣就是正义、永恒的太阳。5世纪中叶以后,圣诞节作为重要节日,成了教会的传统,并在东西派教会中逐渐传开。因所用历法不同等原因,各教派会举行庆祝的具体日期和活动形式也有差别。圣诞节习俗传播到亚洲主要是在十九世纪中叶,日本、韩国等都受到了圣诞文化的影响。现在西方在圣诞节常互赠礼物,举行欢宴,并以圣诞老人、圣诞树等增添节日气氛,已成为普遍习俗。圣诞节也成为西方世界以及其他很多地区的公共假日。

二、创意名

圣诞节就要到了,本篇我们将用html+js写一个动态的烟花代码,程序员的浪漫这不就来了吗,感兴趣的小伙伴可下载学习,安静的在家中读懂它的那一刻,在这疫情肆虐的日子里也是一件很不错的事,将有趣的东西分享给你,希望你度过一个愉快的圣诞节!

三、效果展示

基础版动画效果,有声音

在这里插入图片描述
进阶版动画效果,可点击绽放烟花

在这里插入图片描述

四、烟花代码

动画主要由焰火类,背景图和随机函数等组成。进阶版可点击屏幕直接开始绽放烟花。
以下是HTML部分,完整代码及效果点击下载👉烟花代码
进阶版👉烟花代码2

<!doctype html>
<html><head><meta charset="utf-8"><title>动态烟花代码</title><style>html,* {margin: 0;padding: 0}body {background-image: url(bg.png);background-size: 100% 100%;background-size: 100%; background-repeat:no-repeat;}.demo {margin: 0 auto;width: 100%;height: 100%;}h1 {margin: 150px auto 30px auto;text-align: center;font-family: 'Roboto';}</style>
</head><body><div class="demo"></div><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script><script src="fireworks.js"></script><script>$('.demo').fireworks({sound: true,opacity: 0.6,width: '100%',height: '100%'});</script></body></html>

js部分

// 焰火集合类
class Fireworks {_timer = null_animater = null_useAnimationFrame = truectx = null // 画布上下文,都画这上面offScreenCtx = null // 离屏 canvas,优化性能fps = 60 // 帧率控制fireworks = [] // 焰火数组fireworkCount = 8 // 焰火数量fireworkInterval = 400 // 焰火爆炸间隔💥fireworkColors = DEFAULT_COLORS // 焰火颜色随机取值数组particleOptions = { // 粒子配置size: 15, // 几块钱的烟花speed: 15, // 燃烧的速度gravity: 0.08, // 🌍 地球的引力,向下的power: 0.93, // 动力,值越大冲越远shrink: 0.97, // 燃料消耗的速度jitter: 1, // 摇摇晃摇color: 'hsla(210, 100%, 50%, 1)', // 颜色}constructor(dom, options = {}) {if (!(dom instanceof HTMLElement)) {options = dom || {}}if (!dom) {dom = document.body}this.initCanvas(dom)const { particleOptions = {}, ...others } = optionsthis.particleOptions = { ...this.particleOptions, ...particleOptions }Object.keys(others).forEach(key => this[key] = others[key])this._useAnimationFrame = this.fps >= 60}// 初始化画布initCanvas(dom) {let canvas = domconst isCanvas = canvas.nodeName.toLowerCase() === 'canvas'if (!isCanvas) {canvas = document.createElement('canvas')dom.appendChild(canvas)}const { width, height } = dom.getBoundingClientRect()canvas.width = widthcanvas.height = heightcanvas.style.cssText = `width: ${width}px; height: ${height}px;`this.ctx = canvas.getContext('2d')const offScreenCanvas = canvas.cloneNode()this.offScreenCtx = offScreenCanvas.getContext('2d')}// 创建单个焰火createFirework(x, y, color) {const { ctx, particleOptions, fireworkColors } = thisconst { width, height } = ctx.canvasx = x ?? random(width * 0.1, width * 0.9)y = y ?? random(height * 0.1, height * 0.9)color = color ?? random(fireworkColors)const particleCount = random(80, 100)const firework = new Firework({ particleOptions, particleCount, x, y, color })this.fireworks.push(firework)}// 焰火燃尽,无情灭之checkFireworks() {this.fireworks = this.fireworks.filter(firework => !firework.isBurnOff())}// 检查是否需要创建焰火loop() {let interval = this.fireworkInterval * random(0.5, 1)this._timer = setTimeout(() => {this.checkFireworks()if (this.fireworks.length < this.fireworkCount) {this.createFirework()}this.loop()}, interval)}// 绘制焰火render(animationFunction, interval) {this._animater = animationFunction(() => {const { width, height } = this.ctx.canvas// 通过绘制黑色透明图层,达到尾焰的效果this.ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'this.ctx.fillRect(0, 0, width, height)this.offScreenCtx.clearRect(0, 0, width, height)this.fireworks.forEach(firework => {firework.render(this.offScreenCtx)})this.ctx.save()this.ctx.globalCompositeOperation = 'lighter'this.ctx.drawImage(this.offScreenCtx.canvas, 0, 0, width, height)this.ctx.restore()this.render(animationFunction, interval)}, interval)}// 前进四 !!!start() {this.loop()// 60 帧就用 requestAnimationFrame,否则用 setTimeoutconst animationFunction = this._useAnimationFrame ? requestAnimationFrame : setTimeoutconst interval = 16.67 * (60 / this.fps)this.render(animationFunction, interval)}// 休息一下pause() {this._timer && clearTimeout(this._timer)this._animater && (this._useAnimationFrame ? cancelAnimationFrame(this._animater): clearTimeout(this._animater))this._timer = nullthis._animater = null}// 结束吧这个世界stop() {this.pause()this.fireworks.length = 0const { width, height } = this.ctx.canvas()this.ctx.clearRect(0, 0, width, height)}}// 焰火类class Firework {_status = STATUS.INITx = 0y = 0color = 'rgba(255, 255, 255, 1)'particleCount = 80particles = []particleOptions = {}constructor(options = {}) {Object.keys(options).forEach(key => this[key] = options[key])this._status = STATUS.INITthis.initParticles()}// 初始化粒子initParticles() {const { x, y, color, particleOptions } = thisconst { size: baseSize } = particleOptionsfor (let index = 0; index < this.particleCount; index++) {const size = random(-baseSize / 2, baseSize / 2) + baseSizeconst particle = new Particle({ ...particleOptions, x, y, size, color })this.particles.push(particle)}}// 更新粒子updateParticles() {this.particles.forEach(particle => particle.update())this.particles = this.particles.filter(particle => !particle.isBurnOff())// 拥有的粒子都燃尽了,自己也就结束了if (this.particles.length === 0) {this._status = STATUS.COMPLETED}}// 渲染粒子render(ctx) {this.updateParticles()if (this.isBurnOff()) returnthis.particles.forEach(particle => {particle.render(ctx)})}isBurnOff() {return this._status === STATUS.COMPLETED}}// 焰火粒子类class Particle {size = 10speed = 15gravity = 0.2power = 0.92shrink = 0.93jitter = 0.08color = 'hsla(210, 100%, 50%, 1)'shadowColor = 'hsla(210, 100%, 50%, 0.1)'x = 0 // x 坐标位置y = 0 // y 坐标位置vel = { // 速度x: 0,y: 0,}constructor(options) {Object.keys(options).forEach(key => {this[key] = options[key]})const angle = random(0, Math.PI * 2)const speed = Math.cos(random(0, Math.PI / 2)) * this.speedthis.vel = {x: Math.cos(angle) * speed,y: Math.sin(angle) * speed,}this.shadowColor = tinycolor(this.color).setAlpha(0.1)}// 移形换位update() {this.vel.x *= this.powerthis.vel.y *= this.powerthis.vel.y += this.gravityconst jitter = random(-1, 1) * this.jitterthis.x += this.vel.x + jitterthis.y += this.vel.y + jitterthis.size *= this.shrink}// 绘制单粒子render(ctx) {if (this.isBurnOff()) returnctx.save()const { x, y, size, color, shadowColor } = this// 红里透白,像极了爱情const gradient = ctx.createRadialGradient(x, y, 0, x, y, size / 2)gradient.addColorStop(0.1, 'rgba(255, 255, 255, 0.3)')gradient.addColorStop(0.6, color)gradient.addColorStop(1, shadowColor)ctx.fillStyle = gradient// ctx.beginPath()// ctx.arc(x, y, size, 0, Math.PI * 2, true)// ctx.closePath()// ctx.fill()// 绘制矩形性能更好ctx.fillRect(x, y, size, size)ctx.restore()}// 小到看不到isBurnOff() {return this.size < 1}}

五、总结

圣诞节,玲儿响,温情祝福传递忙;喜盛宴,披红装,圣诞金娃送吉祥;夜月美,心儿醉,吉祥安康永相随;平安夜,送平安,幸福快乐人变美。最后,祝所有和我一样即将考研的人旗开得胜,坚持就是胜利,世上无难事,只要肯攀登。

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

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

相关文章

平衡二叉树的一系列操作:删除、插入(在二叉排序树中插入新结点后,如何保持平衡)、调整平衡等等等

平衡二叉树的插入&#xff08;在二叉排序树中插入新结点后&#xff0c;如何保持平衡&#xff09;1.平衡二叉树的定义2.平衡二叉树的插入&#xff08;调整最小不平衡子树A&#xff09;2.1LL&#xff08;在A的左孩子的左子树中插入导致不平衡&#xff09;2.2RR&#xff08;在A的右…

qt嵌入并运行外部exe

由于项目需要&#xff0c;要实现将一个外部exe运行在qt的窗口中。下面记录一下过程&#xff1a; 首先就是在qt中创建一个新项目 由于我这里没有用到画布&#xff0c;所以没有勾选Generate form 然后就会自动生成一个可运行的代码 然后将我下边的代码替换粘贴进去 #includ…

cubeIDE开发, UART的CubeMX及HAL库实现原理及底层分析

一、UART通信协议 UART通用异步收发器(Universal Asynchronous Receiver and Transmitter)是STM32 上常用的串行通信外设&#xff0c;可以灵活地与外部设备进行全双工数据交换&#xff0c;需要注意区别&#xff1a; 【1】USART-通用同步异步收发器(Universal Synchronous Async…

stm32f407VET6 系统学习 day04 DHT11 温湿度传感器

1.温湿度的一次完整的数据包括&#xff1a; 一次完整的数据传输为40bit,高位先出。 数据格式: 8bit湿度整数数据 8bit湿度小数数据 8bi温度整数数据 8bit温度小数数据 8bit校验&#xff08;校验和的值是前四个字节数据的和) 用户MCU发送一次开始信号后,DHT11从低功耗模式转…

UDP协议在Windows上使用示例

UDP(User Datagram Protocol&#xff0c;用户数据报协议)是无连接的&#xff0c;因此在两个进程通信前没有握手过程。UDP协议提供一种不可靠数据传送服务&#xff0c;也就是说&#xff0c;当进程将一个报文发送进UDP套接字时&#xff0c;UDP协议并不保证该报文将到达接收进程。…

为什么要使用 Compose 来开发 Android ?

1. Compose诞生背景 近年来&#xff0c;以React为代表的声明式UI开发思想席卷了整个前端开发领域。客户端与前端在产品形态上非常相似&#xff0c;也希望借鉴这种全新的开发思想来提升客户端UI的开发效率和体验。在这个大背景下&#xff0c;Android与iOS平台相继发布了自己的声…

node.js+uni计算机毕设项目互联网教育系统小程序(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

Attetion is all you need论文阅读笔记

Attetion is all you need 参考&#xff1a;沐神&#xff08; 沐神_论文精讲_Attention is all you need&#xff09; 1、Abstract 主流的序列转录模型&#xff08;给一个序列生成另一个序列&#xff0c;比如机器翻译&#xff0c;给一句英文&#xff0c;生成一句中文&#x…

Biotin-PEG-MAL,Maleimide-PEG-Biotin,生物素聚乙二醇马来酰亚胺

英文名称&#xff1a;Biotin-PEG-MAL&#xff0c;Maleimide-PEG-Biotin 中文名称&#xff1a;生物素聚乙二醇马来酰亚胺 Biotin-PEG-Mal&#xff0c;聚乙二醇化生物素对亲和素或链霉亲和素有很高的亲和力。生物素/亲和素体系在生物分子检测和分离中有着广泛的应用。马来酰亚胺…

【状态估计】电力系统状态估计中的异常检测与分类(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

LeetCode 1739. 放置盒子:数学 思维

【LetMeFly】1739.放置盒子 力扣题目链接&#xff1a;https://leetcode.cn/problems/building-boxes/ 有一个立方体房间&#xff0c;其长度、宽度和高度都等于 n 个单位。请你在房间里放置 n 个盒子&#xff0c;每个盒子都是一个单位边长的立方体。放置规则如下&#xff1a; …

408 考研《操作系统》第三章第二节:基本分页存储管理、两级页表、基本分段存储管理方式、段页式管理方式

文章目录教程1. 基本分页存储管理的基本概念1.1 连续分配方式的缺点1.2 把“固定分区分配”改造为“非连续分配版本”1.3 什么是分页存储1.4 如何实现地址的转换&#xff1f;1.5 逻辑地址结构1.6 重要的数据结构——页表1.7 知识回顾与重要考点2. 基本地址变换机构2.1 例题2.2 …

单链表的头插法与尾插法

一、基本概念 二、头叉法 该方法从一个空链表开始&#xff0c;生成新结点&#xff0c;并将读取到的数据存放到新结点的数据域中&#xff0c;然后将新结点插入到当前链表的表头。采用头插法创建单链表时&#xff0c;读入数据的顺序与生成单链表的元素顺序是相反的。 LinkList L…

JavaScript操作BOM对象

BOM&#xff1a;浏览器对象模型 window代表浏览器窗口 >window.alert(1) undefined >window.innerHeight //浏览器内部高度 242 >window.innerWidth 1229 >window.outerHeight //浏览器外部高度 824 >window.outerWidth 1536 Navigator&#xff0c;封装了浏…

Kafka消息写入流程

Kafka消息写入流程 0,写入消息简要流程图 1,从示例开始 在Kafka中,Producer实例是线程安全的,通常一个Producer的进程只需要生成一个Producer实例. 这样比一个进程中生成多个Producer实例的效率反而会更高. 在Producer的配置中,可以配置Producer的每个batch的内存缓冲区的大小…

DAY5 Recommended system cold startup problem

推荐系统的冷启动问题 推荐系统冷启动概念 ⽤户冷启动&#xff1a;如何为新⽤户做个性化推荐物品冷启动&#xff1a;如何将新物品推荐给⽤户&#xff08;协同过滤&#xff09;系统冷启动&#xff1a;⽤户冷启动物品冷启动本质是推荐系统依赖历史数据&#xff0c;没有历史数据⽆…

【工作流Activiti7】6、Activiti 7 源码学习

1. 启动分析 源码版本是 7.1.0.M6 首先从 ProcessEngineAutoConfiguration 开始 ProcessEngineAutoConfiguration 是activiti-spring-boot-starter 7.1.0.M6自动配置的入口类&#xff0c;在这里主要看 SpringProcessEngineConfiguration 主要是配置了自动部署 最最最重要的…

Linux网络编程之epoll多路转接服务器

Linux网络编程之epoll多路转接服务器 一、epoll的基本概念 epoll是Linux下多路复用IO接口select/poll的增强版本&#xff0c;它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率&#xff0c;因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待…

算法 | 如何通过Math.random()方法实现X平方或更多次方的概率?

前言 本文主要介绍Java中Math.random()方法以及该方法的简单应用。 每种语言都有随机方法&#xff0c;在Java中的随机方法有Math.random()方法、Random类。 Math.random Math.random()方法的返回值的是double类型&#xff0c;其返回值的范围为[0,1)&#xff0c;包含0&#…

KOOM线上APM监控最全剖析

APM&#xff0c;全称是Application Performance Management&#xff0c;也就是应用性能管理&#xff0c;这与我们平时写的业务可能并不相关&#xff0c;但是却承载着App线上稳定的责任。当一款App发布到线上之后&#xff0c;不同的用户有不同场景&#xff0c;一旦App出现了问题…