实现带有轨迹的动态五角星动画效果 - 使用HTML5 Canvas

今天有位群友遇到一个流行拖尾的特效,实现的方法有很多,也可以直接让PE和UI直接实现,但是我们Html5 Canvas也可以实现,在本文中,我们将通过一个简单的HTML5 Canvas动画项目,介绍如何绘制动态五角星并为它们添加拖尾效果。通过这一过程,我们不仅能实现星星的动态运动,还能看到它们留下一条渐变消失的轨迹,创造出令人惊叹的星空效果。

一、HTML结构

HTML文档的结构非常简洁,主要包含了一个canvas元素,它用于呈现所有的绘图内容。我们将通过JavaScript来操作这个canvas,并动态更新其中的图形。

xml 复制代码
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Star with Trail</title>
    <style>
      body, html {
        margin: 0;
        height: 100%;
        overflow: hidden;
      }
      canvas {
        display: block;
        background: black;
      }
    </style>
  </head>
  <body>
    <canvas id="starCanvas"></canvas>
  </body>
</html>

二、Canvas设置与样式

首先,我们为canvas设置了一个全屏大小,使其填充整个浏览器窗口。通过window.innerWidthwindow.innerHeight获取窗口的宽高,确保动画在不同屏幕上都能完整显示。

ini 复制代码
const canvas = document.getElementById("starCanvas");
const ctx = canvas.getContext("2d");

// 设置画布大小
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

为了确保背景是黑色的,同时避免滚动条出现,我们在CSS中做了如下样式调整:

css 复制代码
body, html {
  margin: 0;
  height: 100%;
  overflow: hidden;
}
canvas {
  display: block;
  background: black;
}

三、五角星绘制函数

在这个动画中,我们使用了一个drawStar函数来绘制五角星。五角星是通过计算五个顶点位置来绘制的,顶点之间的角度是固定的。函数接受四个参数:x(星星的X坐标),y(Y坐标),radius(星星的半径),color(星星的颜色)。

ini 复制代码
function drawStar(x, y, radius, color) {
  const spikes = 5; // 五个尖刺
  const step = Math.PI / spikes;
  const rotation = (Math.PI / 2) * 3; // 初始旋转角度
  const outerRadius = radius;
  const innerRadius = radius / 2;

  ctx.beginPath();
  ctx.moveTo(x, y - outerRadius);

  for (let i = 0; i < spikes; i++) {
    ctx.lineTo(
      x + Math.cos(rotation + step * i) * outerRadius,
      y + Math.sin(rotation + step * i) * outerRadius,
    );
    ctx.lineTo(
      x + Math.cos(rotation + step * i + step / 2) * innerRadius,
      y + Math.sin(rotation + step * i + step / 2) * innerRadius,
    );
  }

  ctx.closePath();
  ctx.fillStyle = color;
  ctx.fill();
}

四、星星对象与轨迹

为了使星星具有动态效果,我们创建了一个Star类,包含了星星的位置、大小、速度以及其轨迹。星星会随时间不断更新其位置,并在其移动的过程中留下轨迹。

轨迹的消失效果通过记录每个轨迹点的时间戳来实现,随着时间的推移,轨迹的透明度会逐渐减小,直到完全消失。

kotlin 复制代码
class Star {
  constructor(x, y, size, speedX, speedY) {
    this.x = x;
    this.y = y;
    this.size = size;
    this.speedX = speedX;
    this.speedY = speedY;
    this.trail = []; // 存储轨迹
    this.trailLifetime = 1000; // 轨迹存活时间 3 秒
  }

  // 绘制星星和轨迹
  draw() {
    // 添加新的轨迹点
    this.trail.push({ x: this.x, y: this.y, time: Date.now() });

    // 清除已过期的轨迹点
    this.trail = this.trail.filter((point) => Date.now() - point.time < this.trailLifetime);

    // 绘制轨迹点
    for (let i = 0; i < this.trail.length; i++) {
      const trailPoint = this.trail[i];
      const alpha = 1 - (Date.now() - trailPoint.time) / this.trailLifetime; // 轨迹的透明度随时间变化
      ctx.beginPath();
      ctx.arc(trailPoint.x, trailPoint.y, this.size / 3, 0, Math.PI * 2);
      ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`; // 轨迹点透明度
      ctx.fill();
    }

    // 绘制五角星
    drawStar(this.x, this.y, this.size, "white");
  }

  // 更新星星位置
  update() {
    this.x += this.speedX;
    this.y += this.speedY;

    // 随机改变速度,模拟不规则的运动
    this.speedX += (Math.random() - 0.5) * 0.2;
    this.speedY += (Math.random() - 0.5) * 0.2;

    // 如果星星超出屏幕,重置其位置
    if (this.x > canvas.width) this.x = 0;
    if (this.x < 0) this.x = canvas.width;
    if (this.y > canvas.height) this.y = 0;
    if (this.y < 0) this.y = canvas.height;
  }
}

五、创建并更新星星

我们创建了一个星星数组,数组中的每个星星对象都有独立的运动轨迹和动态效果。星星的位置和速度是随机生成的,但为了简化展示,我们先只生成一个较大的星星。

ini 复制代码
const stars = [];
for (let i = 0; i < 1; i++) {
  const size = Math.random() * 5 + 1;
  const speedX = Math.random() * 2 - 1;
  const speedY = Math.random() * 2 - 1;
  const star = new Star(
    canvas.width / 4,
    canvas.height / 4,
    10,
    Math.random() * 2 - 1,
    Math.random() * 2 - 1,
  );
  stars.push(star);
}

六、动画循环

为了让动画不断循环,我们使用requestAnimationFrame来创建一个平滑的动画效果。在每一帧,我们都清除画布,更新并绘制所有星星。

scss 复制代码
function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布
  for (let i = 0; i < stars.length; i++) {
    stars[i].update();
    stars[i].draw();
  }
  requestAnimationFrame(animate);
}

animate();

七、完整代码

ini 复制代码
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Star with Trail</title>
    <style>
      body,
      html {
        margin: 0;
        height: 100%;
        overflow: hidden;
      }
      canvas {
        display: block;
        background: black;
      }
    </style>
  </head>
  <body>
    <canvas id="starCanvas"></canvas>

    <script>
      const canvas = document.getElementById("starCanvas");
      const ctx = canvas.getContext("2d");

      // 设置画布大小
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;

      // 五角星绘制函数
      function drawStar(x, y, radius, color) {
        const spikes = 5;
        const step = Math.PI / spikes;
        const rotation = (Math.PI / 2) * 3;
        const outerRadius = radius;
        const innerRadius = radius / 2;

        ctx.beginPath();
        ctx.moveTo(x, y - outerRadius);

        for (let i = 0; i < spikes; i++) {
          ctx.lineTo(
            x + Math.cos(rotation + step * i) * outerRadius,
            y + Math.sin(rotation + step * i) * outerRadius,
          );
          ctx.lineTo(
            x + Math.cos(rotation + step * i + step / 2) * innerRadius,
            y + Math.sin(rotation + step * i + step / 2) * innerRadius,
          );
        }

        ctx.closePath();
        ctx.fillStyle = color;
        ctx.fill();
      }

      // 星星对象
      class Star {
        constructor(x, y, size, speedX, speedY) {
          this.x = x;
          this.y = y;
          this.size = size;
          this.speedX = speedX;
          this.speedY = speedY;
          this.trail = []; // 存储轨迹
          this.trailLifetime = 1000; // 轨迹存活时间 3 秒
        }

        // 绘制星星和轨迹
        draw() {
          // 添加新的轨迹点
          this.trail.push({ x: this.x, y: this.y, time: Date.now() });

          // 清除已过期的轨迹点
          this.trail = this.trail.filter((point) => Date.now() - point.time < this.trailLifetime);

          // 绘制轨迹点
          for (let i = 0; i < this.trail.length; i++) {
            const trailPoint = this.trail[i];
            const alpha = 1 - (Date.now() - trailPoint.time) / this.trailLifetime; // 轨迹的透明度随时间变化
            ctx.beginPath();
            ctx.arc(trailPoint.x, trailPoint.y, this.size / 3, 0, Math.PI * 2);
            ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`; // 轨迹点透明度
            ctx.fill();
          }

          // 绘制五角星
          drawStar(this.x, this.y, this.size, "white");
        }

        // 更新星星位置
        update() {
          this.x += this.speedX;
          this.y += this.speedY;

          // 随机改变速度,模拟不规则的运动
          this.speedX += (Math.random() - 0.5) * 0.2;
          this.speedY += (Math.random() - 0.5) * 0.2;

          // 如果星星超出屏幕,重置其位置
          if (this.x > canvas.width) this.x = 0;
          if (this.x < 0) this.x = canvas.width;
          if (this.y > canvas.height) this.y = 0;
          if (this.y < 0) this.y = canvas.height;
        }
      }

      // 创建星星
      const stars = [];
      for (let i = 0; i < 1; i++) {
        const size = Math.random() * 5 + 1;
        const speedX = Math.random() * 2 - 1;
        const speedY = Math.random() * 2 - 1;
        //   const star = new Star(Math.random() * canvas.width, Math.random() * canvas.height, size, speedX, speedY);
        // 创建一个大的星星
        const star = new Star(
          canvas.width / 4,
          canvas.height / 4,
          10,
          Math.random() * 2 - 1,
          Math.random() * 2 - 1,
        );

        stars.push(star);
      }

      // 动画循环
      function animate() {
        ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布
        for (let i = 0; i < stars.length; i++) {
          stars[i].update();
          stars[i].draw();
        }
        requestAnimationFrame(animate);
      }

      animate();
    </script>
  </body>
</html>

八、总结

通过这段代码,我们成功实现了一个带有动态轨迹的五角星动画效果。你可以看到,每个星星都有自己的运动轨迹,并且随着时间的推移,轨迹会逐渐消失,给人一种真实的星星划过夜空的感觉。通过canvasarcbeginPath等方法,我们能够精确控制每个星星的外形和动画效果。此外,我们还通过随机的速度和位置来模拟星星的不规则运动,增加了动画的趣味性。

完结 撒花~

相关推荐
桂月二二1 分钟前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062061 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb1 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角1 小时前
CSS 颜色
前端·css
浪浪山小白兔3 小时前
HTML5 新表单属性详解
前端·html·html5
lee5763 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579653 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me3 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者3 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架
qq_392794484 小时前
前端缓存策略:强缓存与协商缓存深度剖析
前端·缓存