持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
前言
最近在小破站闲逛,看到了很多有意思的内容,也学到了很多有用的知识,刚好最近学到了一个非常炫酷、非常炸裂的星星闪耀效果,今天就带着大家一起来实现一下这闪瞎眼的星。老规矩还是先看一下最终实现的效果,然后再来一步步分析实现的原理,如下:
这个效果是不是非常的闪耀,非常的炸裂呢?下面我们就一起来学习一下如何制作这么一个闪耀的星星吧!
五角星
这个效果是使用 canvas
来开发的,因此我们需要准备好最基础的内容,也就是在页面中准备好一个 canvas
,它的样式也很简单,我们一起来看一下相关的 html
和 css
,如下:
<canvas id="canvas"></canvas>
html
中只有一个 canvas
标签。再来看一下 css
:
*{margin: 0; padding: 0;}
body {
background: #000;
overflow: hidden;
}
css
也很简单,只需要将 body
的背景色设置为黑色,并且将 body
的超出部分进行隐藏即可。
我们先来实现一个静态的五角星,有了静态的五角星,然后再添加周围的发射光线就简单很多了。那么要实现一个五角星该如何做呢?
这里还是需要借助我们在前面学到的三角函数相关的知识,利用 Math.sin()
和 Math.cos()
函数来获取两个夹角之间的弧度。因为要实现五角星,其实就是要实现五个夹角的弧度,并且将这五个夹角连接在一起,最后就能画出一个完整的五角星了,下面我们一起来看一下相关的代码,如下:
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('canvas');
const ctx = this.canvas.getContext('2d');
canvas.width = innerWidth;
canvas.height = innerHeight;
const points = [];
const radius1 = 100; // 外五角星半径
const radius2 = 50; // 内五角星半径
首先我们准备好相关的初始内容,最上面的 @type {HTMLCanvasElement}
可以告诉编辑器我们是在编写 canvas
相关的内容,这样编辑器就能给予我们相关的提示内容了,这样就不怕不记得 canvas
相关的 api
该怎么写了。
基础的内容都准备好以后,我们先将五角星的五个顶点的坐标轴获取到,这里的顶点包含了外层的五个顶点坐标以及内层的五个顶点坐标,因此我们需要将相关的数据放到 points
数组中,相关的代码如下:
// 创建五角星的五个顶点
for (let i = 0; i < 5; i++) {
// 外层五角星坐标
let deg = -90 + i * 72;
let x1 = radius1 * Math.cos(deg * Math.PI / 180) + canvas.width / 2;
let y1 = radius1 * Math.sin(deg * Math.PI / 180) + canvas.height / 2;
points.push([x1, y1]);
// 旋转36度,生成内顶角坐标
deg = deg + 36;
let x2 = radius2 * Math.cos(deg * Math.PI / 180) + canvas.width / 2;
let y2 = radius2 * Math.sin(deg * Math.PI / 180) + canvas.height / 2;
points.push([x2, y2]);
}
这块的内容主要还是用到了三角函数相关的知识点,如果对三角函数不了解,可能会看的比较蒙,如果看不明白,可以看一下前面的文章,里面有介绍三角函数相关的知识点,相信你看完三角函数相关的内容再来看这里就明白了。
当上述的数据都准备好后,我们就可以正式开始来绘制五角星了。有了这些数据,绘制起来也就比较简单了,一起来看一下代码,如下:
function drawStart() {
// 清理画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 开始绘制
ctx.beginPath();
// 连接生成的五角星顶点
for (let i in points) {
// 遍历各个顶点坐标,然后绘制出来
let p = points[i];
ctx.lineTo(p[0], p[1]);
}
ctx.closePath();
ctx.fillStyle = `hsl(${Math.random() * 360}, 80%, 60%)`;
ctx.fill();
}
上述的代码很简单,都是 canvas
最基础的操作,最终实现的效果如下图所示:
在上面我们设置这个五角星的背景色是随机色,因此页面刷新后五角星的颜色就会随机的变换。
我们可以给这个静态的五角星添加一个动画,只需要添加简单的几行代码就可以实现,如下:
function animate() {
requestAnimationFrame(animate);
drawStart();
}
添加动画后,实现的效果如下所示:
闪耀的效果已经出来了,由于录制的 GIF
丢帧严重,因此建议大家自行在本地实现相关的代码再来看效果,这样会更好。
目前五角星已经实现了,还剩下每个方法的放射粒子效果了,接下来我们一起来看一下如何实现放射粒子吧!
五角星粒子放射
在最前面的效果中,我们可以看到满屏的粒子是从五角星的每一条边中发射出来的,并且这些粒子在发射的过程中会逐渐的消失,因此我们首先想到的就是,这些粒子应该是存放在某个对象中,这样当对象中的粒子数达到一个临界值时,就删除最先生成的粒子,然后再不断的添加新的粒子。
有了这个思路,我们就先来实现一个粒子。还记得我们在前面一节中如何生成烟花的爆炸效果吗?这里要实现粒子的放射其实原理跟前面也是差不多的,下面我们一起来看一下相关的代码,如下:
class Particle {
constructor(x, y, canvas, ctx) {
// 创建粒子角度
this.deg = Math.atan2((y - canvas.height / 2), (x - canvas.width / 2));
// 粒子与原点之间的角度和距离
this.radius = Math.sqrt(Math.pow((y - canvas.height / 2), 2) + Math.pow((x - canvas.width / 2), 2));
this.age = Math.random() * canvas.width / 2;
this.color = `hsl(${Math.random() * 360}, 80%, 60%)`;
this.canvas = canvas;
this.ctx = ctx;
}
draw() {
let x1 = this.radius * Math.cos(this.deg) + this.canvas.width / 2;
let y1 = this.radius * Math.sin(this.deg) + this.canvas.height / 2;
this.ctx.fillStyle = this.color;
this.ctx.beginPath();
this.ctx.arc(x1, y1, 2, 0, Math.PI * 2, 0);
this.ctx.fill();
}
update() {
this.radius += 2;
this.age--;
}
}
我们还是通过面向对象的方式来实现粒子类,这样就可以通过循环遍历不断的生成 N多个 不同的粒子。有了上面生成粒子的类,接下来我们就需要改造一下前面的代码,让五角星能够配合粒子的放射。一起来看一下代码吧,如下:
// ...other code
const particles = []; // 需要新增一个粒子存放的数组
// 主要修改 drawStart 方法
drawStar() {
// 要实现拖尾效果,就不能使用 clearRect,需要改成 fillRect
ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
// 使用 fillRect 创建拖尾效果
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 创建粒子数据,如果当前粒子数组中的粒子数量少于800,则添加100个
if (particles.length < 800) {
// 先创建 100 个粒子
for (let i = 0; i < 100; i++) {
// 随机生成一个从0到10的值
let s = Math.random() * 10 | 0;
// 根据上面生成的随机值,随机选择一个顶点
let p1 = points[s];
// 选择跟前一个顶点相邻的顶点,如果选择的这个顶点是最后一个,则下一个顶点是第一个
let p2 = points[(s + 1) % 10];
// 随机获取当前这条线的x轴的值
let px = Math.random() * (p2[0] - p1[0]) + p1[0];
// 获取这条线与x轴相交的坐标
let py = (px - p1[0]) * (p2[1] - p1[1]) / (p2[0] - p1[0]) + p1[1];
particles.push(new Particle(px, py, canvas, ctx));
}
// ...other code
}
// 渲染粒子效果
for (let i in particles) {
let p = particles[i];
p.update();
p.draw();
if (p.age < 0) {
particles.splice(i, 1);
}
}
}
只需要设置好粒子的生成点,这样当我们使用 requestAnimationFrame
让五角星动起来的时候,就会不断的生成新的粒子,并且每个粒子的生成点都是随机的,最终实现的完整代码可以在这里进行查看:
总结
canvas
能够实现很多炫酷的效果,前提是需要学习一些数学相关的知识点,因为我们需要借助这些数学中的方法来生成一些数据,只有数据获取到了,才能实现我们想要的效果。关于三角函数,这都是初中的知识点,当初没有好好学习,现在就是还债的时候,让我们一起加油吧!
最后,如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,谢谢大家