「万事胜意🧧」你可能不知道的烟花秀🎆

简介: 「万事胜意🧧」你可能不知道的烟花秀🎆

🙇 前言


  • 转眼间又到了一年春节,而今年的春节也正好是我的本命年🐯。
  • 因为疫情的原因可能又回不了家过年了,还是很想回去看看烟花感受下年味的🧧。
  • 既然回不去那就自己做一个吧~跟大家一起赏烟花🎆。
  • Ps: 本文没有涉及到性能优化,请不要在正式项目使用喔~


🏮 ToDoList


  • 获取文字像素点
  • 初始化烟花
  • 烟花发射
  • 烟花爆炸


🧧 Just Do It


获取文字像素点

  • 首先我们先创建一个canvas
<!-- index.html -->
<canvas id="textFireWorks"></canvas>
复制代码
  • 初始化canvas并在canvas中填充想要输出的文字
// fireWork.js
let textCanvas, textCtx;
const canvasWidth = window.innerWidth;
const canvasHeight = window.innerHeight;
const fontSize =180
function fireWorksShowBegin() {
  initCanvas();
}
function initCanvas() {
  textCanvas = document.getElementById("textFireWorks");
  textCtx = textCanvas.getContext("2d");
  textCanvas.style.width = canvasWidth + "px";
  textCanvas.style.height = canvasHeight + "px";
  textCanvas.width = canvasWidth;
  textCanvas.height = canvasHeight;
  textCtx.textAlign = "center";
  textCtx.textBaseline = "top";
  textCtx.font = fontSize + 'px "宋体"';
  textCtx.fillStyle = "#fff";
  textCtx.fillText("新春快乐", canvasWidth / 2, 0);
}
复制代码


image

  • canvas初始化完成后我们需要获取每个像素点对应的位置
// fireWork.js
let textPixels = [];
function initCanvas() {
  // ...
  //获取画布位置
  let pix = textCtx.getImageData(0, 0, canvasWidth, canvasHeight).data;
  let gap = 6;
  for (let h = 0; h < canvasHeight; h += gap) {
    for (let w = 0; w < canvasWidth; w += gap) {
      // 当前像素块相对于画布的索引位置
      let position = (canvasWidth * h + w) * 4;
      let r = pix[position],
          g = pix[position + 1],
          b = pix[position + 2];
      if (r + g + b !== 0) {
        textPixels.push({
          x: w,
          y: h,
        });
      }
    }
  }
 }
复制代码
  • canvas中我们可以通过getImageData方法拿到画布的信息
  • 其中的data就是色彩信息,每4个元素表示一个像素颜色
  • 我们可以通过以上算法在水平和垂直方向均以固定间隙去读取imageData像素点信息,如果是完全不透明的像素点,则作为我们需要的关键坐标保存下来至textPixels数组中用于我们之后烟花渲染。

image


初始化烟花

  • 对于烟花的呈现在这里我使用了一个PixiJS库,这是一个HTML5创建引擎,用它可以很方便的渲染2D动画。
  • 首先引入该库后我们创建一个容器和渲染器添加到我们的dom中。
// fireWork.js
// 创建一个Container
const stage = new PIXI.Container();
//自动检测渲染器
const renderer = PIXI.autoDetectRenderer(canvasWidth, canvasHeight);
document.body.appendChild(renderer.view);
复制代码
  • 接下来我们需要将烟花最终绽放的位置摆满烟花,也就是以上像素点的位置。
  • 使用PIXI.Texture我将福的图标作为烟花占位符。
  • 将每一个像素点都替换成福图标。
  • stage容器中添加这些子节点,并把每一个firework记录下来方便接下来使用。
// fireWork.js
const fireworks = [];
const yOffset = canvasHeight * 0.4;
const textures = PIXI.Texture.from("https://s3.bmp.ovh/imgs/2022/01/0d7afb4d0700761e.png");
function fireWorksShowBegin() {
  //...
  initFireworks();
}
function initFireworks() {
  // shuffle(textPixels);
  for (let i = 0, l = textPixels.length; i < l; i++) {
    createEmojiFirework(textures, textPixels[i], i);
  }
}
function createEmojiFirework(text, pos, i) {
  const size = 20;
  const firework = new PIXI.Sprite(text);
  firework.position.x = pos.x;
  firework.position.y = pos.y + yOffset;
  firework.width = size;
  firework.height = size;
  firework.image = text;
  fireworks.push(firework);
  stage.addChild(firework);
}
复制代码
// fireWork.js
function fireWorksShowBegin() {
  //...
  requestAnimationFrame(fireWorksAnimate);
}
function fireWorksAnimate() {
  requestAnimationFrame(fireWorksAnimate);
  // 将对象渲染到其 WebGL 视图。
  renderer.render(stage);
}
复制代码
  • 我们来看看现在的效果吧

image


烟花发射

  • 现在最终需要呈现的效果已经做好了,我们只需要在循环动画fireWorksAnimate方法中将每一个图标都慢慢发射到对应的像素点即可。
  • fireWorksAnimate中我们首先需要做一件事情,那就是将图标的位置从一个地方位移到我们真正想要烟花爆炸💥的位置,但是在这之前我们已经将图标放到爆炸的位置了,现在我们需要对初始化创建的图标做处理重新给定一个起点记录爆炸的位置让他缓慢位移。
  • 我们需要改动createEmojiFirework方法,设置起点position(x,y)和终点explodePositio(x,y)并设置图标移动速度speed
// fireWork.js
function createEmojiFirework(text, pos, i) {
  //...
  // 记录最终爆炸的位置
  firework.explodePosition = {
    x: pos.x,
    y: pos.y + yOffset,
  };
  //给图标一个起点位置
  firework.position.x = 20;
  firework.position.y = 30;
  //设置图标移动速度
  firework.speed = 0.02
}
复制代码
  • 而在fireWorksAnimate中我们需要计算从起点到终点的每次位移。
// fireWork.js
function fireWorksAnimate() {
  for (let i = 0; i < fireworks.length; i++) {
    fireworks[i].position.x +=
      (fireworks[i].explodePosition.x - fireworks[i].position.x) *
      fireworks[i].speed;
    fireworks[i].position.y +=
      (fireworks[i].explodePosition.y - fireworks[i].position.y) *
      fireworks[i].speed;
  }
}
复制代码
  • 现在的效果是这样的

image

  • 好家伙效果是移动了,但是太整齐了,我们在createEmojiFirework中给烟花一个定时器让他延迟一个一个的发射,这下效果就好很多了。

image


烟花爆炸

  • 烟花发射成功了,接下来我们要完善烟花爆炸的效果。
  • 爆炸的原理其实也是跟生成图标差不多。
    • 在每一次的动画中循环中我们都要计算图标是否快要到达终点。
    • 如果快要到达就给它一个标记并触发爆炸事件。
    • 在爆炸事件中我们需要生成多个粒子,给每个粒子初始化不同的x轴y轴的位移速度,并且记录大小和位置。
// fireWork.js
let particles = [];
function fireWorksAnimate() {
  //...
  for (let i = 0; i < fireworks.length; i++) {
  //...
    if (!fireworks[i].exploded) {
      //计算是否快要到达终点
      if (
        Math.abs(fireworks[i].position.x - fireworks[i].explodePosition.x) +
          Math.abs(fireworks[i].position.y - fireworks[i].explodePosition.y) <
        100
      ) {
        fireworks[i].exploded = true;
        explodeFirework(fireworks[i]);
      }
    }
  }
 //...
}
function explodeFirework(firework) {
  for (let i = 0; i < 20; i++) {
    const size = 20;
    let particle = new PIXI.Sprite(firework.image);
    particle.speed = {
      x: (Math.random() - 0.5) * (Math.random() * 10),
      y: (Math.random() - 0.5) * (Math.random() * 10),
    };
    particle.position.x = firework.position.x;
    particle.position.y = firework.position.y;
    particle.width = size;
    particle.height = size;
    particles.push(particle);
    stage.addChild(particle);
  }
}
复制代码
  • 至此每个图标烟花就会在到达终点后生成20个相同大小的例子,但是这个例子一直存在于画布中,我们需要计算他的位移产生一种爆炸的效果。
  • 在每次画布重新渲染中我们将每一个粒子都按照它自身的速度分别在xy位移,并设置alpha不透明度递减。
// fireWork.js
function fireWorksAnimate() {
  //...
  for (let i = 0, l = particles.length; i < l; i++) {
      particles[i].position.x += particles[i].speed.x;
      particles[i].position.y += particles[i].speed.y;
      particles[i].speed.y += 0.03;
      particles[i].alpha -= 0.01;
    }
 //...
}
复制代码
  • 最后呈现的效果就是这样啦~~

image

  • 但是现在的效果太统一了,如果当我们将发射位置 终点位置 发射速度 爆炸大小全部随机之后会发生什么呢?

image


最终效果

  • 好啦这样想要的效果就制作完成了,接下来就加上小卢给大家的新年贺语就结束了(贺卡有彩蛋喔~😆)。

image


👋 写在最后


  • 首先还是很感谢大家看到这里,这次的文章就分享到这里,提前祝大家春节快乐!!
  • 在新的一年希望大家越来越好,顺顺利利,疫情早日过去!!!!
  • 如果您觉得这篇文章有帮助到您的的话不妨🍉🍉关注+点赞+收藏+评论+转发🍉🍉支持一下哟~~😛您的支持就是我更新的最大动力。
  • 如果想跟我一起讨论和学习更多的前端知识可以加入我的前端交流学习群,大家一起畅谈天下~~~
相关文章
|
6月前
浪漫3D圣诞树特效【附源码】Merry Christmas to My Girl !
浪漫3D圣诞树特效【附源码】Merry Christmas to My Girl !
54 1
|
7月前
超简单的html+css魔幻霓虹灯文字特效
超简单的html+css魔幻霓虹灯文字特效
59 3
超简单的html+css魔幻霓虹灯文字特效
|
7月前
|
数据采集 前端开发 JavaScript
💗中秋💗CSS动画 | 嫦娥奔月
💗中秋💗CSS动画 | 嫦娥奔月
75 2
|
7月前
|
前端开发 安全 JavaScript
html+css+js实现的新年烟花
html+css+js实现的新年烟花
77 0
|
前端开发 JavaScript
七夕表白,不给女朋友来场炫酷的烟花?
七夕表白,不给女朋友来场炫酷的烟花?
96 0
|
Python
【兔年烟花】旖旎风景——浪漫烟花(Python实现)
【兔年烟花】旖旎风景——浪漫烟花(Python实现)
146 0
除夕最炫烟花代码
除夕最炫烟花代码
167 0
|
前端开发 机器人 程序员
六一 特效~ 你也是大小孩
六一 特效~ 你也是大小孩
113 0
|
C语言 C++
C/C++实现跨年表白烟花
C/C++实现跨年表白烟花
521 0
|
小程序 开发工具
樱花飘落模拟器-情人节祝你表白成功
看着樱花缓缓的飘落,然后不觉间竟下起了绵绵的细雨。因为今天我所在的城市正下着小雨,所以就在这个小应用中增加了阵阵的细雨功能。 下面我们就学习一下如何实现一个这样温暖的小程序。 首先准备一下素材。一个粉色的背景,两个樱花花瓣,一个模拟雨滴的长方形,以及两句要显示的话。
136 0
下一篇
DataWorks