初始canvas动画 - 文字雨

529 阅读1分钟

QQ录屏20230517143027.gif

今天来做一个文字动画

分析

需要用到canvas的绘制文字的apifillText(),传入3个参数,文字、x坐标、y坐标
刚开始是一行一行文字的显示,可以使用这个api来实现
先给文字设置一个sizectx.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];
  }