放个烟花迎接龙年春节吧

不知不觉即将迎来2024龙年春节了。龙的形象在中国传统文化中有着广泛的应用,比如在传统文化中,龙代表着权力、威严、吉祥和神灵的象征,同时也是生命力和繁荣的象征。

今天的文章将用原生JavaScriptCanvas API实现一个烟花的效果,效果如下所示,在放烟花的过程中将「龙年大吉」的文字逐渐显示出来。

接下来开始具体的代码实现过程,针对重点实现代码进行解析,详情完整代码请看源码实现。烟花效果通常由多个元素组成,包括烟花、粒子、画布等。以下是对代码中关键部分的详细解析:

Fireworks 类

Fireworks 类定义了烟花的行为,包括创建、绘制和更新烟花。其中的 canvasLoop 方法用于循环绘制画布,drawFireworks 方法用于绘制烟花的效果,updateFireworks 方法用于更新烟花的位置和状态。

// Fireworks 类
var Fireworks = function () {
  // ... 省略部分代码 ...
  self.canvasLoop = function () {
    // 循环绘制画布
    window.requestAnimationFrame(self.canvasLoop, self.canvas);
    self.ctx.globalCompositeOperation = 'destination-out';
    self.ctx.fillStyle = 'rgba(0,0,0,' + self.clearAlpha / 100 + ')';
    self.ctx.fillRect(0, 0, self.cw, self.ch);
    self.updateFireworks();
    self.updateParticles();
    self.drawFireworks();
    self.drawParticles();
  };
  // ... 省略部分代码 ...
  self.drawFireworks = function () {
    // 绘制烟花效果
  };
  self.updateFireworks = function () {
    // 更新烟花状态
  };
  self.createParticles = function () {
    // 绘制粒子效果
  };
  self.updateParticles = function () {
    // 更新粒子状态
  };
};

Particle 类

Particle 类表示烟花中的粒子,包括粒子的位置、速度、颜色等属性。在代码中,粒子的更新和绘制分别由 updatedraw 方法实现。

// Particle 类
class Particle {
  constructor(pos, target, vel, color, radius) {
    // 粒子属性的初始化
    this.pos = pos;
    this.target = target;
    this.vel = vel;
    this.color = color;
    this.radius = radius;
    this.direction = 0;
  }
  set(type, value) {
    this[type] = value;
  }
  // 更新粒子状态
  update() {
    this.radius = 2;
    this.vel.x = (this.pos.x - this.target.x) / drag;
    this.vel.y = (this.pos.y - this.target.y) / drag;
    this.pos.x -= this.vel.x;
    this.pos.y -= this.vel.y;
  }
  // 绘制粒子
  draw() {
    ctx.beginPath();
    ctx.fillStyle = this.color;
    ctx.arc(this.pos.x, this.pos.y, this.radius, 0, Math.PI * 2);
    ctx.fill();
  }
}

changeText 函数

changeText 函数用于在画布上绘制文字,并根据文字生成粒子效果(调用Particle类)。它通过获取画布上的像素数据,根据像素的不透明度生成粒子,并将这些粒子添加到 particles 数组中。

function changeText(text) {
  var current = 0,
    temp, radius, color;
  ctx.fillStyle = "#fff";
  ctx.font = "160px 宋体";
  ctx.fillText(text, can.width * 0.5 - ctx.measureText(text).width * 0.5, can.height * 0.5 + 60);
  var data = ctx.getImageData(0, 0, can.width, can.height).data;
  for (i = 0; i < data.length; i += 12) {
    if (data[i] !== 0 && (Math.random() * 10) >= 7.8) {
      radius = max_radius - Math.random() * min_radius;
      temp = { x: (i / 4) % can.width, y: ((i / 4) / can.width) };
      color = colors[0];
      var p = new Particle(
        temp, { x: (i / 4) % can.width, y: ((i / 4) / can.width) }, { x: 0, y: 0 },
        color,
        radius);
      particles.push(p);
      ++current;
    }
  }
  particles.splice(current, particles.length - current);
}

在程序初始化执行时运行changeText("龙年大吉"),这样即可触发对传入文字逐渐显示的烟花效果。

draw 函数

draw 函数用于绘制单个粒子,根据传入的参数绘制指定位置和颜色的圆形粒子。

function draw(obj) {
  ctx.beginPath();
  ctx.arc(obj.target.x, obj.target.y, obj.radius, 0, 2 * Math.PI);
  ctx.fillStyle = obj.color;
  ctx.fill();
}

init 函数

init 函数是整个烟花效果的初始化函数,它通过循环绘制粒子的方式实现烟花效果。在每一帧中,它会绘制下一个粒子,并根据条件创建新的烟花效果。

function init() {
  id = window.requestAnimationFrame(init)
  if (t >= particles.length - 1) {
    window.cancelAnimationFrame(id)
  }
  draw(particles[t])
  t++;
  var rand = function (rMi, rMa) { return ~~((Math.random() * (rMa - rMi + 1)) + rMi); }
  if (t % 8 == 0) {
    fworks.currentHue = rand(0, 360);
    fworks.createFireworks(window.innerWidth / 2, window. innerHeight, particles[t].pos.x, particles[t].pos.y);
  }
}

以上是对代码中关键部分的解析,通过这些代码,即可实现一个炫丽的烟花效果,部分代码量较大没有完整贴出,有兴趣可以查阅源码了解。

点击鼠标放烟花

基于以上代码,监听鼠标事件,用户点击时通过createFireworks创建新的烟花。

self.canvas.addEventListener('mousedown', function (e) {
  self.mx = e.pageX - self.canvas.offsetLeft;
  self.my = e.pageY - self.canvas.offsetTop;
  self.currentHue = rand(self.hueMin, self.hueMax);
  self.createFireworks(self.cw / 2, self.ch, self.mx, self.my);
});

点击效果如下:

最后

本文利用原生JavaScript和Canvas API创造出一个很不错烟花视觉效果,并在烟花中逐渐显示出「龙年大吉」的文字,有兴趣可以修改代码传入其他文字的效果。

关注公众号回复【 20240127 】可获取完整源代码~

参考

原效果参考,代码有所删改:www.jq22.com/jquery-info17933


看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

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

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

相关文章

使用Docker部署MySQL并结合内网穿透实现远程访问本地数据库

文章目录 前言1 .安装Docker2. 使用Docker拉取MySQL镜像3. 创建并启动MySQL容器4. 本地连接测试4.1 安装MySQL图形化界面工具4.2 使用MySQL Workbench连接测试 5. 公网远程访问本地MySQL5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 前言 本文主…

以太网的 MAC 层

目录 1. MAC 层的硬件地址 48 位的 MAC 地址 2. MAC 帧的格式 以太网 V2 的 MAC 帧格式 无效的 MAC 帧 IEEE 802.3 MAC 与以太网 V2 MAC 帧格式的区别 1. MAC 层的硬件地址 硬件地址又称为物理地址&#xff0c;或 MAC 地址。 IEEE 802 标准为局域网规定了一种 48 位…

GitHub无法完成推送 的设置选项

GitHub无法完成推送 的设置选项 系统设置 VS中控制台设置【指令】 控制台调出方法 以下为VS控制台指令 git config --global --unset http.proxy git config --global --unset https.proxygit config --global http.proxy 127.0.0.1:7890 git config --global https.proxy …

JAVA学习笔记三

1.java执行流程分析 2.什么是编译 javac Hello.java 1.有了java源文件&#xff0c;通过编译器将其编译成JVM可以识别的字节码文件 2.在该源文件目录下&#xff0c;通过javac编译工具对Hello.java文件进行编译 3.如果程序没有错误&#xff0c;没有任何提示&#xff0c;但在…

AI代理产品大汇总

目前做AI Agents相关产品的&#xff0c;可以看这个最全汇总 1. 最新的AI Agents 列表编制完成。 2. 列表包括:多种使用案例、开源或闭源状态、以及最新的AI Agent产品等筛选条件。 3. 这个列表每周都在不断收到新的项目提交。 4 该列表可以让学生和AI从业者快速了解当前AI生…

C++快速幂详解简单易懂

引言&#xff1a; 如果我们计算a的k次幂&#xff0c;循环k次每次 a&#xff0c;时间复杂度O(k)&#xff0c;现在我们要把其优化为log(k)的时间复杂度。另外a的k次幂极有可能报long long&#xff0c;比如2的64次幂就已经爆long long 了&#xff0c;所以在k很小的时候就会爆掉l…

RHCE 部署Ubuntu系统(ubuntu-23.10-live-server-amd64.iso)

目录 一、新建虚拟机 二、安装系统 1、 选择安装语言&#xff0c;默认 【 English 】&#xff0c;直接回车 2、选择键盘&#xff0c;默认回车 3、安装的服务器版本&#xff0c;根据需求自行选择&#xff0c;本次安装选择 【 Ubuntu Server 】 4、网络设置&#xff0c;此…

Linux抽象文件系统

一.概念 Linux采用了抽象文件系统的概念来统一管理不同类型的文件和文件系统。抽象文件系统是对不同文件系统的封装&#xff0c;使得用户和应用程序可以以相同的方式访问和操作不同类型的文件系统。 Linux的抽象文件系统通过以下几个组件来实现&#xff1a; VFS&#xff08;V…

(七)springboot实战——springboot3集成R2DBC实现webflux响应式编程服务案例

前言 本节主要内容是关于使用新版springboot3集成响应式数据库R2DBC,完成响应式web服务案例。需要注意的是&#xff0c;此次项目使用的JDK版本是JDK17&#xff0c;springboot版本使用3.2.2版本&#xff0c;数据库使用关系型数据库mysql。WebFlux 是一个基于响应式编程模型的框…

taskflow 源码阅读笔记-1

之前写了一篇介绍Taskflow的短文&#xff1a;传送门 Taskflow做那种有前后依赖关系的任务管理还是不错的&#xff0c;而且他的源码里运用了大量C17的写法&#xff0c;觉得还是非常值得学习的&#xff0c;因此决定看一下他的源码&#xff0c;这里顺便写了一篇代码学习笔记。 概…

【新书推荐】2.6节 原码、反码和补码

回顾上一节中&#xff0c;我们讲解了整数的编码规则。 无符号整数编码规则&#xff1a;无符号整数全部都是正数&#xff0c;是什么就存什么。 有符号整数编码规则&#xff1a;有符号整数最高有效位为0是正数&#xff0c;最高有效位为1是负数。 本节内容&#xff1a;原码、反…

【C++】类和对象(中篇)(全网最细!!!)

文章目录 &#x1f354;一、类的六个默认成员函数&#x1f354;二、构造函数&#x1f35f;1、概念&#x1f35f;2、特性&#x1f369;默认构造函数 &#x1f354;三、析构函数&#x1f35f;1、概念&#x1f35f;2、特性&#x1f369;默认析构函数 &#x1f354;四、拷贝构造函数…

单片机开发板-硬件设计

开发板设计 1> 概述2> 功能2.1> GPIO类2.2> 通信类2.3> 显示类 3> 测试 1> 概述 开发板的定位&#xff1a;学会单片机&#xff1b; 目的越单纯&#xff0c;做的东西越好玩&#xff1b; 51开发板&#xff1a;DAYi STM32F103开发板&#xff1a;DAEr STM32F…

项目中从需求分析到研发上线

一、背景 应用系统从设想到需求到研发到上线会经历一些列工程化过程。比如经典的瀑布模型工作流&#xff0c;其实就是一个经过很多经验总结下来的工程方法。本节阐述项目中从需求到研发上线的过程。但是也有些根据不同的行业&#xff0c;不同的公司&#xff0c;不同管理者的风…

Go 知识for-range

Go 知识for-range 1. for-range 的用法1.1 数组1.2 切片1.3 字符串1.4 map1.5 chan 2. 原理2.1 数组2.2 切片2.3 字符串2.4 map2.5 chan 3. 总结 https://a18792721831.github.io/ 1. for-range 的用法 for-range 表达式用于遍历集合元素&#xff0c;比传统的for更加简单直观…

【微信小程序】15分钟倒计时(附带天数和时钟的实现方法在文章中)

这是制作的订单支付前倒计时&#xff0c;如果客户在规定时间内没能 支付&#xff0c;则系统自动删除&#xff0c;这样就以便有些商品冗余&#xff0c;当然了&#xff0c;这里只有分钟和秒钟&#xff0c;天数和时钟我写在了最底下&#xff0c;最后代码的显示第七行&#xff0c;可…

C++:引用

目录 概念&#xff1a; 引用的使用格式&#xff1a; 引用特性&#xff1a; 常引用 使用场景&#xff1a; 1、做参数 二级指针时的取别名 一级指针取别名 一般函数取别名 2、做返回值 函数返回值的原理&#xff1a; 引用的返回值使用&#xff1a; 引用和指针的对比&…

搭建AI问答和AI绘画小程序都需要做什么?

1、注册和认证小程序 在微信公众平台 注册&#xff0c;选择小程序类别即可。根据提示提交企业相关资质文件即可&#xff0c;注册后进行认证小程序&#xff0c;官方会收取300元认证费用。也可以私信我可以免掉300元认证费。 2、开通微信商家支付 认证通过后&#xff0c;在“功…

uniapp 使用echarts做折线图条形图。

提前10天把中烟活动做完了&#xff0c;以为能打酱油到除夕那天&#xff0c;结果又要做什么数据看板&#xff0c;方便烟草领导过年查看数据&#xff0c;还只给5天时间&#xff0c;真实压榨剥削啊&#xff0c;下辈子再也不‘拍黄片’了&#xff0c;不&#xff01;下份工作我就转前…

MySQL:函数

基本介绍 在MySQL中&#xff0c;为了提高代码重用性和隐藏实现细节&#xff0c;MySQL提供了很多函数。函数可以理解为别人封装好的模板代码。 在MySQL中&#xff0c;函数非常多&#xff0c;主要可以分为五类&#xff1a;聚合函数、数学函数、字符串函数、日期函数、控制流函数、…