Particle Logo

在 React / Next.js 项目里加入 Logo 粒子动画

React 导出是一个内置了 Logo 点阵的 .tsx 文件,任何 React 项目都能用;在 Next.js App Router 里需要多加一行。

更新于

你会得到什么

1. 导出组件

  1. 打开工坊。
  2. 上传 Logo:点击选择 PNG、SVG、JPG 或 WebP 文件,也可以拖到页面上,或按 Ctrl+V / ⌘+V 粘贴。透明背景或纯色背景的 Logo 效果最好;如果有部分没采到,可以调节点阵密度和提取阈值。
  3. 从 9 种效果里选一个,调整粒子大小、形状(方块或圆点)和速度。
  4. 点击导出代码,切到 React 组件 标签,点下载文件(或复制代码)。这个格式需要 Pro。

2. 放进项目

把文件保存为 src/components/PixelLogoLoader.tsx,然后:

import { PixelLogoLoader } from './components/PixelLogoLoader';

export default function Hero() {
  return <PixelLogoLoader height={420} />;
}

Next.js App Router

导出的文件没有 'use client' 声明。它用到了 Hooks 和 Canvas,所以要在 PixelLogoLoader.tsx 第一行加上 'use client';(或者只在客户端组件里引入它):

'use client';

import React, { useEffect, useRef } from 'react';
// ...文件其余部分不变

3. 参数

参数类型默认值作用
variantstring导出时选的效果播放哪种效果,可选值见下表
widthnumber | string'100%'数字按像素计算
heightnumber | string420数字按像素计算
autoPlaybooleantrue自动循环播放:每轮 duration 秒,之后停 1.2 秒
durationnumber3.2每轮的秒数
progressnumber无0 到 100。传入后动画按这个值显示,不再自动播放
colorsstring[]导出时选的配色粒子颜色;自带颜色的点(原图配色)保留自己的颜色
particleSizenumber导出时的大小基础粒子大小,会按容器尺寸缩放
particleShape'square' | 'circle'导出时的形状方块或圆点
speedMultipliernumber导出时的速度粒子移向目标位置的速度倍数
interactivebooleantrue是否响应鼠标:经过时推开粒子,点击触发冲击波
classNamestring无加在外层 div 上
styleCSSProperties无合并到外层 div 的样式之后,可覆盖默认外观

外层 div 默认是黑底、16 像素圆角、细边框和阴影,可以用 style 覆盖:

<PixelLogoLoader
  height={320}
  style={{ background: 'transparent', border: 'none', boxShadow: 'none' }}
/>

progress、variant、duration、autoPlay、speedMultiplier、interactive 每一帧都会重新读取,改了立即生效。colors、particleSize、particleShape 只在创建粒子时使用(组件挂载和容器尺寸变化时);想中途修改,可以给组件换一个新的 key 让它重新挂载。variant 可选值:

variant 值效果
condense量子凝聚态
mobius-flow莫比乌斯拓扑光流
vortex星系引力坍缩
scan全息光栅断层扫描
diffusion-denoise扩散降噪重构
flux-wave超导磁通涟漪
swarm-assembly纳米蜂群智能组装
gravitational-slingshot引力弹弓时间逆流
cymatics-resonance克拉尼声波共振

4. 做成加载页

传入 progress 后,粒子只移动到这个进度对应的位置,加载完成时 Logo 正好成形:

import { useEffect, useState, type ReactNode } from 'react';
import { PixelLogoLoader } from './components/PixelLogoLoader';

export function AppShell({ children }: { children: ReactNode }) {
  const [progress, setProgress] = useState(0);
  const [ready, setReady] = useState(false);

  useEffect(() => {
    // 换成你自己的加载步骤
    const steps = [() => fetch('/api/user'), () => fetch('/api/projects')];
    (async () => {
      for (let i = 0; i < steps.length; i++) {
        await steps[i]();
        setProgress(((i + 1) / steps.length) * 100);
      }
      setReady(true);
    })();
  }, []);

  if (!ready) return <PixelLogoLoader progress={progress} height={360} />;
  return <>{children}</>;
}

5. 性能与无障碍

进入工坊

其他教程