今天来做一个文字动画
分析
需要用到canvas的绘制文字的api:fillText(),传入3个参数,文字、x坐标、y坐标
刚开始是一行一行文字的显示,可以使用这个api来实现
先给文字设置一个size:ctx.font = '10px'
每一行的文字数量:canvas的宽度 / 每一个文字的宽度
// 10 为上面设置的文字size
const columns = Math.floor(canvas.width / 10)
每一个文字的坐标:
- x - 在行中的位置(index) * 文字
size - y - 第几行 * 文字
size\
文字位置:左对齐,顶端对齐
颜色渐变:每渲染一行增加一个有透明度的遮罩覆盖整个画面
实现
首先是从第一行开始逐行渲染, 先声明一个长度为 columns 的数组,里面存储需要渲染的纵坐标y(也就是第几行),将数组全部填充为0,遍历数组开始渲染,结束之后进行 +1。
const charIndex = new Array(columns).fill(0);
function draw() {
ctx.fillStyle = `rgba(0, 0, 0,0.06)`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#b97611";
ctx.font = `${fontSize}px 'Roboto Mono' `;
ctx.textAlign = "left";
ctx.textBaseline = "top";
charIndex.forEach((item, index) => {
const x = index * fontSize;
const y = item * fontSize;
ctx.fillText(getRandomText(), x, y);
charIndex[index]++;
});
}
加入动画 一帧渲染一次
requestAnimationFrame(() => {
draw();
});
渲染到最下面的时候,将charIndex数组归零,就可以重新从上面开始渲染,将归零的数组下标增添随机化,每次只归零部分下标,可实现后面的单列随机渲染。
if(y > canvas.height && Math.random() > 0.99){
charIndex[index] = 0;
}
完整代码
// template
<canvas id="canvas"></canvas>
// js
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth * devicePixelRatio;
canvas.height = window.innerHeight * devicePixelRatio;
const fontSize = 12 * devicePixelRatio;
const columns = Math.floor(canvas.width / fontSize);
const charIndex = new Array(columns).fill(0);
function draw() {
ctx.fillStyle = `rgba(0, 0, 0,0.06)`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#b97611";
ctx.font = `${fontSize}px 'Roboto Mono' `;
ctx.textAlign = "left";
ctx.textBaseline = "top";
charIndex.forEach((item, index) => {
const x = index * fontSize;
const y = item * fontSize;
ctx.fillText(getRandomText(), x, y);
charIndex[index]++;
if(y > canvas.height && Math.random() > 0.99){
charIndex[index] = 0;
}
});
requestAnimationFrame(() => {
draw();
});
}
draw();
function getRandomText() {
const texts = "abcdefghijklmnopqrstuvwxyz0123456789";
const index = Math.floor(Math.random() * texts.length);
return texts[index];
}