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

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

🙇 前言


  • 转眼间又到了一年春节,而今年的春节也正好是我的本命年🐯。
  • 因为疫情的原因可能又回不了家过年了,还是很想回去看看烟花感受下年味的🧧。
  • 既然回不去那就自己做一个吧~跟大家一起赏烟花🎆。
  • 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


👋 写在最后


  • 首先还是很感谢大家看到这里,这次的文章就分享到这里,提前祝大家春节快乐!!
  • 在新的一年希望大家越来越好,顺顺利利,疫情早日过去!!!!
  • 如果您觉得这篇文章有帮助到您的的话不妨🍉🍉关注+点赞+收藏+评论+转发🍉🍉支持一下哟~~😛您的支持就是我更新的最大动力。
  • 如果想跟我一起讨论和学习更多的前端知识可以加入我的前端交流学习群,大家一起畅谈天下~~~
相关文章
|
29天前
|
C++
浪漫七夕流星雨
关于如何使用C++和EasyX图形库创建一个带有流星雨和背景音乐的浪漫七夕表白程序的教程。
30 0
浪漫七夕流星雨
|
6月前
|
前端开发 安全 JavaScript
html+css+js实现的新年烟花
html+css+js实现的新年烟花
63 0
|
前端开发 JavaScript
七夕表白,不给女朋友来场炫酷的烟花?
七夕表白,不给女朋友来场炫酷的烟花?
87 0
|
对象存储
七夕快到了,来创造一副浪漫的鹊桥插画吧
本次通过加载和推理SD模型对象存储OSS Bucket,挂载到PAI-EAS服务,实现模型部署,加载和推理SD模型,制作属于自己的七夕画作。
除夕最炫烟花代码
除夕最炫烟花代码
114 0
|
Python
【兔年烟花】旖旎风景——浪漫烟花(Python实现)
【兔年烟花】旖旎风景——浪漫烟花(Python实现)
141 0
|
前端开发 机器人 程序员
六一 特效~ 你也是大小孩
六一 特效~ 你也是大小孩
106 0
|
C语言 C++
C/C++实现跨年表白烟花
C/C++实现跨年表白烟花
436 0
|
前端开发 JavaScript
2023跨年代码(烟花+背景音乐)
2023跨年代码(烟花+背景音乐)
327 0
|
小程序
樱花飘落模拟器-请你看樱花静静的飘落
今天是一个美好的日子,所以小蚂蚁决定教大家用微信小游戏制作工具做一个温暖而美好的“樱花飘落模拟器”小程序,然后把它送给所爱的人。 先看一下最终的效果图。
117 0