文章目录
- 一、前言
- 二、创意名
- 三、效果展示
- 四、烟花代码
- 五、总结
一、前言
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}}
五、总结
圣诞节,玲儿响,温情祝福传递忙;喜盛宴,披红装,圣诞金娃送吉祥;夜月美,心儿醉,吉祥安康永相随;平安夜,送平安,幸福快乐人变美。最后,祝所有和我一样即将考研的人旗开得胜,坚持就是胜利,世上无难事,只要肯攀登。