2023过年,又限制放烟花?程序猿有办法!
本篇文章给大家介绍如何用前端代码实现一个烟花绽放的绚烂效果,其实主要就是用前端三剑客来实现,也就是HTML+CSS+JS,下面一起来看一下,作者会解说相应的代码,希望对需要的朋友有所帮助。(ps:之所以有这篇文章是由于作者所在地区禁止放烟花...哈哈)
↑↑↑↑↑↑ 效果图镇楼 ↑↑↑↑↑↑
序
不知道是在什么时候,济南就开始都在传:“今年不再限制放烟花啦!”。一些集市上也开始有了售卖烟花的摊子
大家都很兴奋,很多小伙伴开始购买烟花。特别是今年特别火的 “加特林 ?”
但是大家兴奋劲还没过呢,随着官方 一纸禁令,让咱们知道了:
2023 过春年
烟花依然了无缘
让我们这些屯了烟花的可咋办啊 ??????
不过身为程序猿的我们,能就这么认栽了?
我们可是要用代码改变世界的人啊~~~~
所以我辛苦闭关九九八十一秒(开玩笑~我写了好几天),终于把烟花放到了浏览器上,看着效果我是“内牛满面(泪流满面)”啊!
此时,我真想仰天长啸,大声唱道:
2023 过春年,
烟花依然了无缘;
这能难倒程序猿?
一键三连过大年!
代码
下面开始上菜(代码)咯~~~
咱们整个的代码一共分为三个部分:
html:用来构建项目结构
css:处理文字样式
js(核心):处理烟花逻辑
那么下面,咱们就针对这三个部分,分别进行处理:
1. html
整个 html
分为两部分:
- 文字结构:用来处理右下角的文本
2. canvas 画板:作为烟花渲染区
1. 文字结构
文字结构整体的内容处理会比较简单,通过div
包裹“文本标签”即可:
<!-- 文字修改区 --> <div class="title"> <h2>LGD_Sunday 祝大家:</h2> <h1>2023 新年快乐?</h1> </div>
2. canvas
canvas 作为 web
为我们提供的画板工具,可以帮助咱们绘制各种各样的图形。
那么对于咱们本次的烟花绘制而言,同样需要借助canvas
的能力。
所以在html
区域部分,我们必须提供一个canvas
绘制区:
<!-- 烟花渲染区 --> <canvas></canvas>
html 区域总结
当咱们完成基本的html
绘制之后,运行代码到浏览器,效果应该是这个样子的:
啥都没有对吧,别着急,下面咱们去处理css
部分。
2. css
css
处理的核心目的,是为了帮助咱们绘制文字区域的样式(没错,与烟花无关)。
所以,整个css
区域绘制会比较简单
咱们直接来看代码:
html, body { padding: 0px; margin: 0px; background: #222; font-family: 'Karla', sans-serif; color: #fff; height: 100vh; overflow: hidden; } .title { z-index: 1000; position: fixed; bottom: 12px; right: 12px; // 此处修改了字体 font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif; border: 2px solid #fff; padding: 7.5px 15px; background: rgba(0, 0, 0, 0.5); border-radius: 3px; overflow: hidden; } h1 { text-align: right; font-size: 46px; } h2 { font-size: 36px; } canvas { width: 100%; height: 100%; }
绘制了css
之后,页面效果应该是这个样子的:
3. 核心区域:JavaScript
接下来就让咱们进入烟花绘制,最核心的部分JavaScript
的处理,在这部分咱们要利用canvas
的绘制能力,构建出烟花效果。
整个js
的内容,我们把它分为四大部分:
- 烟花类 Firework:这里咱们会通过
function
构建构造函数,创建出自底向上的烟花升起效果。
2. 火花类 Spark:烟花上升到一定位置,会“绽放“,绽放之后变为”火花“,火花类就是处理绽放之后的火花效果的。
渲染函数 render:想要完成整个绽放,需要对页面进行不断地重绘,否则”动画“会卡在一个点不动。所以此时就需要借助到渲染函数,咱们把它叫做
render
(vue 代码对我影响颇深啊)工具函数:工具函数主要包含两个,咱们分开去说:
- 持续绘制函数 drawCircle:该函数可以帮助我们,在每次重新渲染时,进行烟花和火花的绘制
- 随机色值函数 randomColor:该函数可以帮助我们,得到一个随机的烟花色值,用来生成新的烟花
那么明确好大致分类之后,接下来咱们就一步一步的进行实现。
但是大家要注意:为了保证逻辑的通畅性,咱们需要从工具函数开始进行绘制。
1. 工具函数
在刚才咱们说过,工具函数主要包含两个,那么首先先来看第一个工具函数drawCircle
,它的主要作用是:在每次重新渲染时,进行烟花和火花的绘制
// 获取 canvas 上下文,并指定宽高 let ctx = document.querySelector('canvas').getContext('2d') ctx.canvas.width = window.innerWidth ctx.canvas.height = window.innerHeight /** * 持续绘制 */ function drawCircle(x, y, radius, color) { color = color ctx.fillStyle = color ctx.fillRect(x - radius / 2, y - radius / 2, radius, radius) }
在上面的代码中:
- 首先:我们拿到了
ctx
,也就是CanvasRenderingContext2D
二维渲染上下文 ,利用它可以进行绘制渲染 - 然后:把
canvas
的宽高指定为页面宽高 - 最后:构建了
drawCircle
函数,进行持续绘制。它接收四个参数:x
:绘制的 x 坐标y
:绘制的 y 坐标radius
:点的直径(宽高)color
:色值
那么此时,只要触发 drawCircle
函数,就可以进行持续绘制。
工具函数绘制完成之后,下面我们来看第二个函数:随机色值 randomColor:
/** * 生成随机色值 */ function randomColor() { const r = Math.floor(Math.random() * 255) const g = Math.floor(Math.random() * 255) const b = Math.floor(Math.random() * 255) return `rgb(${r},${g},${b})` }
randomColor
函数,主要利用Math.random
生成了一个 0-255
的随机数,三个随机数共同组成了rgb
色值。
2. 烟花类 Firework
有了工具函数之后,下面咱们就可以处理烟花类 Firework
。
烟花类本质上是:自底向上的,烟花升起效果。 其核心是:生成可以被 drawCircle 绘制的对象
所以它内部必然包含:坐标、绽放点、色彩 等属性:
/** * 烟花构造 */ function Firework(x, y) { // 初始点 this.x = x || Math.random() * ctx.canvas.width this.y = y || ctx.canvas.height // 绽放点 this.burstLocation = (Math.random() * ctx.canvas.height) / 2 // 绽放是否已完毕 this.over = false // 烟花色 this.color = randomColor() }
在上面的代码中:
x、y
:表示烟花升起的坐标。其中y
中默认为浏览器底部,x
则可以随机burstLocation
:表示定义的绽放点。通常小于屏幕高度的一半,即:在屏幕上半部分”绽放“over
:表示当前实例对象是否已经绽放完毕了。完毕的实例将不再处理color
:随机得到的烟花色
仅有属性还不够,因为烟花还需要 ”动起来“,所以咱们还需要为它赋值三个方法,以帮助它进行移动、持续绘制、绽放:
// 初始绽放数 const OVERLAP_NUM = 66 // 刷新速度 ms const TIME_STEP = 16 // 烟花移动的速度与方向控制 const WALK = 0.2 // 火花数组 let sparks = [] // 烟花数组 let fireworks = [] /** * 烟花构造 */ function Firework(x, y) { ... /** * 移动的方法 */ this.move = function () { // 横向偏移 this.x += WALK // 上升与绽放 if (this.y > this.burstLocation) { this.y -= 1 } else { this.burst() } } /** * 持续绘制 */ this.draw = function () { drawCircle(this.x, this.y, 1.5, this.color) } /** * 绽放方法 */ this.burst = function () { // 标记绽放完毕 this.over = true // 碎裂烟花数 let i = Math.floor(Math.random() * 150) + 10 // 构建碎裂对象 while (i--) { sparks.push(new Spark(this.x, this.y, this.color)) } } }
在上面的代码中,咱们一共构建了三个方法:
move
:用来处理烟花上升。在上升的过程中,可以通过this.x += WALK
来进行横向的”微调“,这样会更加漂亮draw
:用来进行持续绘制。主要借助了drawCircle
完成burst
:处理绽放。当烟花上升到指定位置时,就需要进行绽放处理。所有的绽放过程,将交由Spark
类处理。
3. 火花类 Spark
当烟花逐渐上升到一定位置之后,则需要进行绽放。
而所谓的绽放就是:烟花爆炸之后迸现出的火花。这一块的过程,咱们将通过Spark
进行处理。
烟花绽放时,将迸现出大量的火花,其中每一个火花,都是一个Spark
实例。
所以针对于Spark
而言,它代表的是:单个火花,从出现到消亡的过程。
那么对于 Spark
它内部的代码来说,总体也是分为:属性、方法 两部分。
首先咱们先来看属性:
/** * 火花构造 */ function Spark(x, y, color) { // 标记绽放点位置与色值 this.x = x this.y = y this.color = color // 位置 this.dir = Math.random() * (Math.PI * 2) // 执行完毕 this.over = false // 火花崩裂速度 this.speed = Math.random() * 3 + 3 // 火花下坠的速度 this.gravity = Math.random() + 0.1 // 火花消失的速度 this.countdown = this.speed * 10 }
对于以上代码来说:
x、y、color
:表示绽放的位置与色值dir
:表示绽放后的位置over
:表示绽放完成speed
:火花崩裂之后的运行速度gravity
:火花开始下坠时的速度,它在计算时会进行递增(加速)countdown
:消失的倒计时
有了属性之后,下面咱们需要通过两个方法,来保证Spark
的移动和绘制:
/** * 火花构造 */ function Spark(x, y, color) { ... /** * 火花移动方法 */ this.move = function () { // 倒计时处理 this.countdown-- if (this.countdown < 0) { this.over = true } // 速度递减 if (this.speed > 0) { this.speed -= 0.1 } if (this.speed < 0) { return } // x、y 坐标位置 this.x += Math.cos(this.dir + WALK) * this.speed this.y += Math.sin(this.dir + WALK) * this.speed this.y += this.gravity // 下坠速度加快 this.gravity += 0.05 } /** * 绘制 */ this.draw = function () { drawCircle(this.x, this.y, 3, this.color) } }
其中:
move
:代表移动的过程。在这里咱们利用Math.cos 和 Math.sin 计算了坐标位置,并且通过this.gravity += 0.05
增加了烟花下坠的速度。draw
:代表持续绘制。同样需要利用drawCircle
方法。
4. 渲染函数 render
那么最后,咱们就可以来构建render
函数。
render
函数的核心作用是:保证烟花的不断渲染。要达到这个目的,咱们就必须要保证render 函数不断重复执行
想要让render
重复执行其实有两种方式:
1.window.requestAnimationFrame:该方法可以保证高性能的持续重绘。但是 在高刷屏幕下会导致 ”速率过快“2.window.setTimeout:该方法可以通过delay
控制速率,所以在当前场景中比较推荐。
/** * 渲染函数 */ function render() { // 夜幕背景色与区域 ctx.fillStyle = 'rgba(0, 0, 0, 0.1)' ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height) // 烟花上升 for (let firework of fireworks) { if (firework.over) { continue } firework.move() firework.draw() } // 火花下坠 for (let spark of sparks) { if (spark.over) { continue } spark.move() spark.draw() } // 通过随机数来控制烟花产生速度 if (Math.random() < 0.05) { fireworks.push(new Firework()) } // 重复渲染 setTimeout(render, TIME_STEP) }
5. 完整代码
因为整套的js
代码比较多,所以咱们在最后,把整个的js
代码给大家贴出来(因为我不相信你们会一步一步跟着学 ??????),以方便大家随取随用(我是不是很周到??????)
// 获取 canvas 上下文,并指定宽高 let ctx = document.querySelector('canvas').getContext('2d') ctx.canvas.width = window.innerWidth ctx.canvas.height = window.innerHeight // 初始绽放数 const OVERLAP_NUM = 66 // 刷新速度 ms const TIME_STEP = 16 // 烟花移动的速度与方向控制 const WALK = 0.2 // 火花数组 let sparks = [] // 烟花数组 let fireworks = [] // 初始爆炸的填充逻辑 for (let i = 0; i < OVERLAP_NUM; i++) { // 填充 fireworks.push( // 构建随机位置 new Firework( Math.random() * window.innerWidth, Math.random() * window.innerHeight ) ) } /** * 渲染函数 */ function render() { // 夜幕背景色与区域 ctx.fillStyle = 'rgba(0, 0, 0, 0.1)' ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height) // 烟花上升 for (let firework of fireworks) { if (firework.over) { continue } firework.move() firework.draw() } // 火花下坠 for (let spark of sparks) { if (spark.over) { continue } spark.move() spark.draw() } // 通过随机数来控制烟花产生速度 if (Math.random() < 0.05) { fireworks.push(new Firework()) } // 重复渲染 setTimeout(render, TIME_STEP) } /** * 火花构造 */ function Spark(x, y, color) { // 标记绽放点位置与色值 this.x = x this.y = y this.color = color // 位置 this.dir = Math.random() * (Math.PI * 2) // 执行完毕 this.over = false // 火花崩裂速度 this.speed = Math.random() * 3 + 3 // 火花下坠的速度 this.gravity = Math.random() + 0.1 // 火花消失的速度 this.countdown = this.speed * 10 /** * 火花移动方法 */ this.move = function () { // 倒计时处理 this.countdown-- if (this.countdown < 0) { this.over = true } // 速度递减 if (this.speed > 0) { this.speed -= 0.1 } if (this.speed < 0) { return } // x、y 坐标位置 this.x += Math.cos(this.dir + WALK) * this.speed this.y += Math.sin(this.dir + WALK) * this.speed this.y += this.gravity // 下坠速度加快 this.gravity += 0.05 } /** * 绘制 */ this.draw = function () { drawCircle(this.x, this.y, 3, this.color) } } /** * 烟花构造 */ function Firework(x, y) { // 初始点 this.x = x || Math.random() * ctx.canvas.width this.y = y || ctx.canvas.height // 绽放点 this.burstLocation = (Math.random() * ctx.canvas.height) / 2 // 绽放是否已完毕 this.over = false // 烟花色 this.color = randomColor() /** * 移动的方法 */ this.move = function () { // 横向偏移 this.x += WALK // 上升与绽放 if (this.y > this.burstLocation) { this.y -= 1 } else { this.burst() } } /** * 持续绘制 */ this.draw = function () { drawCircle(this.x, this.y, 1.5, this.color) } /** * 绽放方法 */ this.burst = function () { // 标记绽放完毕 this.over = true // 碎裂烟花数 let i = Math.floor(Math.random() * 150) + 10 // 构建碎裂对象 while (i--) { sparks.push(new Spark(this.x, this.y, this.color)) } } } /** * 持续绘制 */ function drawCircle(x, y, radius, color) { color = color ctx.fillStyle = color ctx.fillRect(x - radius / 2, y - radius / 2, radius, radius) } /** * 生成随机色值 */ function randomColor() { const r = Math.floor(Math.random() * 255) const g = Math.floor(Math.random() * 255) const b = Math.floor(Math.random() * 255) return `rgb(${r},${g},${b})` } // 开始 render()
总结
三年抗疫,咱们共同经历了封控、裁员、降薪等一系列让人感到”始料未及“的事情。
我甚至一度以为将来会变成”封控常态化“、”裁员常态化“、”降薪常态化“。
但是在新的2023
年到来之前,所有的一切都已经变成了过去式。
让我们用一场烟花告别过去,迎接未来!
2023 年将会是一个好的年度,大家一起加油!
在这里:Sunday 祝大家:新年快乐,兔年大吉!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











세계 최초의 AI 프로그래머 데빈(Devin)이 태어난 지 한 달도 채 안 된 2022년 3월 3일, 프린스턴 대학의 NLP팀은 오픈소스 AI 프로그래머 SWE-에이전트를 개발했습니다. GPT-4 모델을 활용하여 GitHub 리포지토리의 문제를 자동으로 해결합니다. SWE-bench 테스트 세트에서 SWE-agent의 성능은 Devin과 유사하며 평균 93초가 걸리고 문제의 12.29%를 해결합니다. SWE-agent는 전용 터미널과 상호 작용하여 파일 내용을 열고 검색하고, 자동 구문 검사를 사용하고, 특정 줄을 편집하고, 테스트를 작성 및 실행할 수 있습니다. (참고: 위 내용은 원문 내용을 약간 조정한 것이지만 원문의 핵심 정보는 그대로 유지되며 지정된 단어 수 제한을 초과하지 않습니다.) SWE-A

PHP와 Vue: 프론트엔드 개발 도구의 완벽한 조합 오늘날 인터넷이 빠르게 발전하는 시대에 프론트엔드 개발은 점점 더 중요해지고 있습니다. 사용자가 웹 사이트 및 애플리케이션 경험에 대한 요구 사항이 점점 더 높아짐에 따라 프런트 엔드 개발자는 보다 효율적이고 유연한 도구를 사용하여 반응형 및 대화형 인터페이스를 만들어야 합니다. 프론트엔드 개발 분야의 두 가지 중요한 기술인 PHP와 Vue.js는 함께 사용하면 완벽한 도구라고 볼 수 있습니다. 이 기사에서는 독자가 이 두 가지를 더 잘 이해하고 적용할 수 있도록 PHP와 Vue의 조합과 자세한 코드 예제를 살펴보겠습니다.

C 언어 학습의 매력: 프로그래머의 잠재력을 여는 것 지속적인 기술 발전으로 컴퓨터 프로그래밍은 많은 주목을 받는 분야가 되었습니다. 많은 프로그래밍 언어 중에서 C 언어는 항상 프로그래머들에게 사랑을 받아 왔습니다. C 언어의 단순성, 효율성 및 폭넓은 적용 덕분에 많은 사람들이 프로그래밍 분야에 입문하는 첫 번째 단계는 C 언어입니다. 이 기사에서는 C 언어 학습의 매력과 C 언어 학습을 통해 프로그래머의 잠재력을 발휘하는 방법에 대해 설명합니다. 우선, C 언어 학습의 매력은 단순함에 있습니다. C언어는 다른 프로그래밍 언어에 비해

프론트엔드 개발 인터뷰에서 일반적인 질문은 HTML/CSS 기초, JavaScript 기초, 프레임워크 및 라이브러리, 프로젝트 경험, 알고리즘 및 데이터 구조, 성능 최적화, 크로스 도메인 요청, 프론트엔드 엔지니어링, 디자인 패턴, 새로운 기술 및 트렌드. 면접관 질문은 후보자의 기술적 능력, 프로젝트 경험, 업계 동향에 대한 이해를 평가하기 위해 고안되었습니다. 따라서 지원자는 자신의 능력과 전문성을 입증할 수 있도록 해당 분야에 대한 충분한 준비를 갖추어야 합니다.

JavaScript 튜토리얼: HTTP 상태 코드를 얻는 방법, 특정 코드 예제가 필요합니다. 서문: 웹 개발에서는 서버와의 데이터 상호 작용이 종종 포함됩니다. 서버와 통신할 때 반환된 HTTP 상태 코드를 가져와서 작업의 성공 여부를 확인하고 다양한 상태 코드에 따라 해당 처리를 수행해야 하는 경우가 많습니다. 이 기사에서는 JavaScript를 사용하여 HTTP 상태 코드를 얻는 방법과 몇 가지 실용적인 코드 예제를 제공합니다. XMLHttpRequest 사용

Django는 빠른 개발과 깔끔한 방법을 강조하는 Python으로 작성된 웹 애플리케이션 프레임워크입니다. Django는 웹 프레임워크이지만 Django가 프런트엔드인지 백엔드인지에 대한 질문에 답하려면 프런트엔드와 백엔드의 개념에 대한 깊은 이해가 필요합니다. 프론트엔드는 사용자가 직접 상호작용하는 인터페이스를 의미하고, 백엔드는 HTTP 프로토콜을 통해 데이터와 상호작용하는 서버측 프로그램을 의미합니다. 프론트엔드와 백엔드가 분리되면 프론트엔드와 백엔드 프로그램을 독립적으로 개발하여 각각 비즈니스 로직과 인터랙티브 효과, 데이터 교환을 구현할 수 있습니다.

프론트엔드 ESM이란 무엇입니까? 프론트엔드 개발에서 ESM은 ECMAScript 사양을 기반으로 한 모듈식 개발 방법인 ECMAScriptModules를 참조합니다. ESM은 더 나은 코드 구성, 모듈 간 격리, 재사용성과 같은 많은 이점을 제공합니다. 이 기사에서는 ESM의 기본 개념과 사용법을 소개하고 몇 가지 구체적인 코드 예제를 제공합니다. ESM의 기본 개념 ESM에서는 코드를 여러 모듈로 나눌 수 있으며 각 모듈은 다른 모듈에 대한 일부 인터페이스를 노출합니다.

빠르고 효율적인 프로그래밍 언어인 Go 언어는 백엔드 개발 분야에서 널리 사용됩니다. 그러나 Go 언어를 프런트엔드 개발과 연관시키는 사람은 거의 없습니다. 실제로 프런트엔드 개발에 Go 언어를 사용하면 효율성이 향상될 뿐만 아니라 개발자에게 새로운 지평을 열어줄 수도 있습니다. 이 기사에서는 프런트엔드 개발에 Go 언어를 사용할 수 있는 가능성을 살펴보고 독자가 이 영역을 더 잘 이해할 수 있도록 구체적인 코드 예제를 제공합니다. 전통적인 프런트엔드 개발에서는 사용자 인터페이스를 구축하기 위해 JavaScript, HTML, CSS를 사용하는 경우가 많습니다.