What you get
PixelLogoLoader.vue: a<script setup lang="ts">single-file component with your logo's sampled points (up to 1,600) built in.- Nothing to install besides Vue. The component draws on one canvas with the 2D API.
- The Vue export requires Pro.
1. Export the component
- Open the workbench.
- Upload your logo: click to choose a PNG, SVG, JPG or WebP file, drag it onto the page, or paste it with Ctrl+V / ⌘+V. Logos on a transparent or plain background work best; if parts are missing, adjust the sampling density and threshold.
- Pick one of the 9 effects and adjust particle size, shape (square or round) and speed.
- Click Export Code, open the Vue 3 tab and choose Download File (or copy the code). This format requires Pro.
2. Add it to your app
Save the file as src/components/PixelLogoLoader.vue, then:
<script setup lang="ts">
import PixelLogoLoader from './components/PixelLogoLoader.vue';
</script>
<template>
<PixelLogoLoader :height="420" />
</template>
By default the component is as wide as its container and 420 px tall. The logo is scaled to fit within 72% of the box and centered. The wrapper has a black background, 16 px rounded corners, a thin border and a shadow; change them in the .pixel-loader-container styles at the bottom of the file.
3. Props
| Prop | Type | Default | What it does |
|---|---|---|---|
variant | string | effect chosen at export | Which effect plays; see the values below |
width | number | string | '100%' | Numbers are pixels |
height | number | string | 420 | Numbers are pixels |
autoPlay | boolean | true | Loops the animation: one cycle of duration seconds, then a 1.2 s hold |
duration | number | 3.2 | Seconds per cycle |
progress | number | none | 0 to 100. When set, the animation follows this value instead of playing on its own |
colors | string[] | palette chosen at export | Particle colors; points that carry their own color (original colors) keep it |
particleSize | number | size chosen at export | Base particle size, scaled to the container |
particleShape | 'square' | 'circle' | shape chosen at export | Square or round particles |
speedMultiplier | number | speed chosen at export | How fast particles move toward their targets |
interactive | boolean | true | Hover pushes particles away; a click sends a shockwave |
Changing variant, colors, particleSize or particleShape re-creates the particles. Values for variant:
| variant value | Effect |
|---|---|
condense | Quantum Condense |
mobius-flow | Mobius Contour Flow |
vortex | Vortex Singularity |
scan | Hologram Raster Scan |
diffusion-denoise | Diffusion Denoise |
flux-wave | Superconducting Flux Wave |
swarm-assembly | Autonomous Swarm Assembly |
gravitational-slingshot | Slingshot Time Reversal |
cymatics-resonance | Cymatics Resonance |
4. Use it as a loading screen
With progress set, the particles only move as far as that value, so the logo completes when loading completes:
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import PixelLogoLoader from './components/PixelLogoLoader.vue';
const progress = ref(0);
const ready = ref(false);
onMounted(async () => {
// Replace these with your own loading steps
const steps = [() => fetch('/api/user'), () => fetch('/api/projects')];
for (let i = 0; i < steps.length; i++) {
await steps[i]();
progress.value = ((i + 1) / steps.length) * 100;
}
ready.value = true;
});
</script>
<template>
<PixelLogoLoader v-if="!ready" :progress="progress" :height="360" />
<main v-else>…</main>
</template>
5. Nuxt and server-side rendering
The component only starts drawing in onMounted, so the server renders just its empty container. If your setup still complains during server rendering, wrap it in Nuxt's <ClientOnly>.
6. Performance and accessibility
- Each component runs one requestAnimationFrame loop, which stops in
onBeforeUnmount; the ResizeObserver is disconnected at the same time. - Each component draws up to 1,600 particles. Avoid running many instances at once on low-end phones.
- The component does not check the reduced-motion setting. To respect it, pass a fixed
progressof 100 so the particles form the logo and stay there instead of looping:
<script setup lang="ts">
const reduceMotion =
typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
</script>
<template>
<PixelLogoLoader :progress="reduceMotion ? 100 : undefined" />
</template>