【CSS Tricks】如何做一个粒子效果的logo

news/2024/9/22 3:26:10 标签: css, 前端

效果展示

效果展示

代码展示

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>粒子效果Logo</title>
    <style>css">
      body,
      html {
        margin: 0;
        padding: 0;
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <canvas id="canvas"></canvas>
    <script>
      class Particle {
        constructor(x, y) {
          this.x = Math.random() * canvas.width;
          this.y = Math.random() * canvas.height;
          this.dest = { x, y };
          this.r = Math.random() * 1 * Math.PI;
          this.vx = (Math.random() - 0.5) * 25;
          this.vy = (Math.random() - 0.5) * 25;
          this.accX = 0;
          this.accY = 0;
          this.friction = Math.random() * 0.025 + 0.94;
          this.color = colors[Math.floor(Math.random() * colors.length)];
        }

        render() {
          this.accX = (this.dest.x - this.x) / 1000;
          this.accY = (this.dest.y - this.y) / 1000;
          this.vx += this.accX;
          this.vy += this.accY;
          this.vx *= this.friction;
          this.vy *= this.friction;
          this.x += this.vx;
          this.y += this.vy;

          ctx.fillStyle = this.color;
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.r, Math.PI * 2, false);
          ctx.fill();

          const a = this.x - mouse.x;
          const b = this.y - mouse.y;
          const distance = Math.sqrt(a * a + b * b);
          if (distance < radius * 75) {
            this.accX = (this.x - mouse.x) / 50;
            this.accY = (this.y - mouse.y) / 50;
            this.vx += this.accX;
            this.vy += this.accY;
          }
        }
      }

      const canvas = document.getElementById("canvas");
      const ctx = canvas.getContext("2d");
      let particles = [];
      let mouse = { x: -9999, y: -9999 };
      const colors = ["#3f73fa", "#7ffde1", "#aedce9"];
      let radius = 1.5;

      function onMouseMove(e) {
        mouse.x = e.clientX;
        mouse.y = e.clientY;
      }

      function onTouchMove(e) {
        if (e.touches.length > 0) {
          mouse.x = e.touches[0].clientX;
          mouse.y = e.touches[0].clientY;
        }
      }

      function onTouchEnd(e) {
        mouse.x = -9999;
        mouse.y = -9999;
      }

      function initScene() {
        particles = [];
        const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        for (let x = 0; x < imgData.width; x += 6) {
          for (let y = 0; y < imgData.height; y += 6) {
            const i = (y * imgData.width + x) * 4;
            if (imgData.data[i + 3] > 200) {
              particles.push(new Particle(x, y));
            }
          }
        }
      }

      function render() {
        requestAnimationFrame(render);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        particles.forEach((particle) => particle.render());
      }

      window.addEventListener("resize", () => {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        initScene();
      });
      window.addEventListener("mousemove", onMouseMove);
      window.addEventListener("touchmove", onTouchMove);
      window.addEventListener("touchend", onTouchEnd);

      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      const img = new Image();
      img.onload = () => {
        ctx.drawImage(
          img,
          canvas.width / 2 - img.width / 2,
          canvas.height / 2 - img.height / 2
        );
        initScene();
        render();
      };
      img.src = "./qbbmnn.png";
    </script>
  </body>
</html>

代码注解

代码的主要部分包括粒子类的定义、初始化过程、事件监听和动画循环。

粒子类(Particle)

每个粒子对象都有以下属性:

  • xy:粒子的当前位置。
  • dest.xdest.y:粒子的目标位置。
  • r:粒子随机的大小。
  • vxvy:粒子的水平和垂直速度。
  • accXaccY:粒子的水平和垂直加速度。
  • friction:粒子的摩擦系数,影响其减速。
  • color:粒子的颜色。

render方法,用于更新粒子的位置并绘制它们。这个方法执行以下操作:

  • 计算粒子到目标位置的加速度。
  • 更新粒子的速度,考虑加速度和摩擦力。
  • 根据速度更新粒子的位置。
  • 绘制粒子。

初始化过程

初始化过程包括以下步骤:

  1. 设置画布的宽度和高度以匹配窗口的尺寸。
  2. 创建一个图像对象并设置src属性,以便加载图像。
  3. 当图像加载完成后,绘制到画布上。
  4. 调用initScene函数来创建粒子数组。
    initScene函数执行以下操作:
  5. 清空粒子数组。
  6. 获取画布上图像的数据。
  7. 遍历图像的每个像素,根据像素的透明度决定是否在该位置创建一个粒子。

事件监听

代码监听了以下事件:

  • resize:当窗口大小变化时,调整画布的大小并重新初始化场景。
  • mousemove:当鼠标移动时,更新mouse对象的xy属性。
  • touchmove:适配移动端,当触摸移动时,更新mouse对象的xy属性。
  • touchend:模拟手离开屏幕后,将mouse对象的xy属性重置为初始值。

动画循环

使用requestAnimationFrame根据屏幕刷新率去更新画面:

  1. 清空画布。
  2. 遍历粒子数组,调用每个粒子的render方法。

可以自定义的部分

  • radius:通过调整这个变量的值,控制鼠标弹开粒子的范围。
  • colors:根据自己喜好去填写多个颜色,最少两个。
  • img:可以准备一张透明底白色字的图片,粒子效果会吸附到白色字的笔触上。例如(因为是白色字透明底,所以需要在夜间模式下app才能看清):

图片


http://www.niftyadmin.cn/n/5669580.html

相关文章

Cisco Catalyst 9000 Series Switches, IOS XE Release 17.15.1 ED

Cisco Catalyst 9000 Series Switches, IOS XE Release 17.15.1 ED 思科 Catalyst 9000 交换产品系列 IOS XE 系统软件 请访问原文链接&#xff1a;https://sysin.org/blog/cisco-catalyst-9000/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&…

GDBus.Error.org.bluez.Error.Failed: br-connection-unknown

The error you’re seeing, GDBus.Error.org.bluez.Error.Failed: br-connection-unknown, is typically related to issues with the Bluetooth stack or the pairing process on the Raspberry Pi. Here’s a step-by-step troubleshooting guide to help resolve this issue…

4.C++中程序中的命名空间

咱们在前面的程序中&#xff0c;提到过使用using namespace std;引入这个命名空间&#xff0c;那么std就是由编程系统提供的标准命名空间&#xff0c;那什么是命名空间呢&#xff1f; 想像一下&#xff0c;比如一个年级的学生&#xff0c;在记录的时候出现了重名的情况&#x…

C++校招面经(二)

欢迎关注 0voice GitHub 6、 C 和 Java 区别&#xff08;语⾔特性&#xff0c;垃圾回收&#xff0c;应⽤场景等&#xff09; 指针&#xff1a; Java 语⾔让程序员没法找到指针来直接访问内存&#xff0c;没有指针的概念&#xff0c;并有内存的⾃动管理功能&#xff0c;从⽽…

基于python上门维修预约服务数据分析系统

目录 技术栈和环境说明解决的思路具体实现截图python语言框架介绍技术路线性能/安全/负载方面可行性分析论证python-flask核心代码部分展示python-django核心代码部分展示操作可行性详细视频演示源码获取 技术栈和环境说明 结合用户的使用需求&#xff0c;本系统采用运用较为广…

胤娲科技:谷歌DeepMind祭出蛋白质设计新AI——癌症治疗迎来曙光

在科技的浩瀚星空中&#xff0c;DeepMind的“阿尔法”家族总是能带来令人瞩目的璀璨光芒。这一次&#xff0c;它们再次以惊人的姿态&#xff0c; 将AI的触角深入到了生命的微观世界——蛋白质设计领域&#xff0c;为我们描绘了一幅未来医疗的宏伟蓝图。 想象一下&#xff0c;一…

一文掌握 Prompt:万能框架+优化技巧+常用指标

Prompt 万能框架 在编写 Prompt 时&#xff0c;从0到1的编写出第一版 Prompt 往往是最难的&#xff0c;而基于已有 Prompt 利用各种技巧进行优化则相对简单。善于解决 “数理问题” 的我们在面对这样一个偏 “文理问题” 的任务时&#xff0c;就像小时候写作文一样难以提笔。如…

Spring Boot与gRPC的完美融合:构建高效用户服务与订单服务通信

gRPC 是一种由 Google 开发的高性能、开源的远程过程调用&#xff08;Remote Procedure Call, RPC&#xff09;框架。它允许在不同的计算机系统或进程之间进行通信&#xff0c;使得分布式系统和微服务架构中的服务之间能够轻松地相互调用方法。gRPC 基于 HTTP/2 协议&#xff0…