Particle Logo

How a logo particle animation works

A logo particle animation draws the logo off-screen, keeps a grid of its visible pixels as target points, and moves one particle toward each point on every frame. This page walks through the four steps Particle Logo uses, how each of the nine effects moves its particles, and a short canvas example you can run yourself.

Updated

How do you turn a logo into particles?

  1. Sample. Draw the logo on an off-screen canvas, read its pixels and keep every Nth pixel that belongs to the logo. Each kept pixel is a target point.
  2. Assign. Create one particle per target point, with a random starting position.
  3. Move. On every frame, move each particle a fraction of the remaining distance to its target. The rule that decides the path is what makes one effect different from another.
  4. Draw. Clear one canvas and draw every particle as a small square or circle.

Step 1: How are the points sampled?

At the default step of 4, our three test logos gave 589 points (a white four-letter wordmark), 4,139 points (a five-color geometric mark) and 7,082 points (the Particle Logo mark). The workbench shows the count next to the preview. The code exports keep up to 1,600 of them, evenly spaced; the JSON export keeps all of them.

Step 2: Where do the particles start and where do they go?

Each particle gets a random start inside the canvas and one target point. On every frame the effect's code receives a progress value from 0 to 100, works out where the particle should be at that moment, and moves the particle part of the way there. The fraction is between 0.09 and 0.28 depending on the effect; higher is snappier.

Step 3: How does each effect move its particles?

The table follows the rules in src/engines/morphParticle.ts. An "offset" is extra displacement added on top of the target position.

EffectHow the particles move
Quantum CondenseEach particle travels in a straight line from its start to its target at an even pace for the first 80% of the cycle, then overshoots slightly and settles.
Mobius Contour FlowThe same straight path, plus a sine wave that travels along the order of the points. It pushes particles in and out from the center by up to 4.5 px and fades as the logo forms.
Vortex SingularityEach particle starts 2.25 turns around the center from its target and pushed outward by 65% of the longer canvas side. Both offsets shrink to zero as progress rises, so the particles wind inward.
Hologram Raster ScanA scan line moves from the top of the canvas to the bottom. Particles whose target is above the line fly to it; the others wait near their start at low opacity.
Diffusion DenoiseEvery particle aims for its target plus a random offset of up to ±24 px that shrinks to zero as progress reaches 100.
Superconducting Flux WaveA ring expands from the center. Particles within 60 px of the ring are pushed up to 14 px along the direction from the center and drawn at full opacity; all particles also move toward their targets.
Autonomous Swarm AssemblyParticles are split into four groups by their index. Each group circles the center at 45% of the shorter canvas side; the circle shrinks by up to 80% as progress rises, and the particles ease out of their orbits into their targets.
Slingshot Time ReversalFor the first 38% of the cycle each particle sits 85 px farther from the center than its target. Then it snaps toward the target with a damped wobble of up to 14 px.
Cymatics ResonanceEvery particle aims for its target plus a random offset whose size follows a two-dimensional standing-wave pattern (a sine times a cosine across the canvas) and shrinks to zero as progress rises. The offset is at most ±18 px.

Step 4: How is it drawn?

A canvas example you can run

This code uses only the first three steps and has no dependencies:

<canvas id="logo" width="480" height="480"></canvas>
<script>
  const canvas = document.getElementById('logo');
  const ctx = canvas.getContext('2d');
  const img = new Image();
  img.onload = start;
  img.src = 'logo.png'; // same origin; a PNG or SVG with a transparent background

  function start() {
    // 1. Draw the logo off-screen and read its pixels
    const off = document.createElement('canvas');
    off.width = canvas.width;
    off.height = canvas.height;
    const octx = off.getContext('2d', { willReadFrequently: true });
    const scale = Math.min(off.width / img.width, off.height / img.height) * 0.8;
    const w = img.width * scale, h = img.height * scale;
    octx.drawImage(img, (off.width - w) / 2, (off.height - h) / 2, w, h);
    const data = octx.getImageData(0, 0, off.width, off.height).data;

    // 2. Keep every 4th pixel that is not transparent: these are the targets
    const step = 4;
    const particles = [];
    for (let y = 0; y < off.height; y += step) {
      for (let x = 0; x < off.width; x += step) {
        const i = (y * off.width + x) * 4;
        if (data[i + 3] > 128) {
          particles.push({
            x: Math.random() * canvas.width,   // random start
            y: Math.random() * canvas.height,
            tx: x, ty: y,                       // target on the logo
            color: 'rgb(' + data[i] + ',' + data[i + 1] + ',' + data[i + 2] + ')'
          });
        }
      }
    }

    // 3. Every frame, move each particle a fraction of the way to its target
    function frame() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      for (const p of particles) {
        p.x += (p.tx - p.x) * 0.06;
        p.y += (p.ty - p.y) * 0.06;
        ctx.fillStyle = p.color;
        ctx.fillRect(p.x - 1, p.y - 1, 2, 2);
      }
      requestAnimationFrame(frame);
    }
    frame();
  }
</script>

Common questions

Does Particle Logo use WebGL or Three.js?

No. The exported files draw with the browser's 2D canvas API and have no runtime dependencies.

How many particles can an export hold?

Up to 1,600. The workbench can sample more: with the default step, our three test logos gave 589 to 7,082.

Why does my sampled logo have gaps?

Usually the sampling step is too large or the threshold is wrong. A smaller step captures more points; the threshold and invert switches change which pixels count as the logo, and the workbench's point cloud preview shows exactly which points were captured.

Do I need to write this myself?

No. The HTML, Vue 3 and React exports in the integration guides already include the nine effects, color settings, mouse interaction and a progress prop.

Open the workbench

More guides