Partikel-Hintergrund
Leuchtende Partikel in bis zu sechs Tiefenebenen, mit WebGL gezeichnet. Nahe groß und weich, ferne fein, der Zeiger fächert die Ebenen auf und erhellt seine Umgebung.
Tiefe, die man mit dem Zeiger spürt
Ein Partikelfeld füllt den Raum hinter deinem Text mit leuchtenden Partikeln in mehreren Tiefenebenen. Sie bewegen sich ein wenig mit dem Zeiger, die Seite gewinnt so Tiefe ohne ein einziges 3D-Modell, und ein Schleier hält den Text davor klar.
„Hero mit Tiefe“ setzt ein tiefes Feld aufsteigender Partikel hinter eine mittige Überschrift. Das „Treibende Band“ lässt Partikel seitlich durch ein Band mit Kennzahlen über die ganze Breite treiben. Die „Hervorgehobene Karte“ legt ein dichtes, feines Feld in eine Karte des Rasters. „Langsames Treiben hinter einem Call to Action“ lässt große, langsame Partikel sanft um die Abschlussfläche fallen.
Partikel wirken technisch und ruhig zugleich, sie passen zu Produkten rund um Daten, Sicherheit und KI. Halte das Feld hinter langem Text locker und nur in einer Karte dicht, dann stützt es den Text, statt mit ihm zu konkurrieren.
Details
Was Partikelfeld mitbringt, aus Registry und Quellcode gelesen.
- Kategorie
- 3D-Hintergründe
- Bereich
- Visuals
- Variants
- 4
- Version
- 1.0.0 · seit 1.2.0
- Datei
- components/ui/particle-field.tsx
- Bringt mit
- utilskitwebgl
- npm-Pakete
- Keine
- Sprachen
- Texte kommen über Props
- Studio
- Im Code anpassen
- Mit KI bauen
- Per MCP in Claude, Cursor, Copilot und Codex
Props
Die Schnittstelle ParticleFieldProps aus components/ui/particle-field.tsx. Beschreibungen stammen aus den Kommentaren im Code und sind auf Englisch. Nimmt außerdem alle Props von ShaderLayerProps an.
densityoptionalnumberParticles per layer, 1 is the designed density, 2 twice as many
layersoptionalnumberDepth layers on desktop, 2 to 6, default 5. Phones draw about half.
directionoptionalnumberDirection of the drift in degrees, 90 rises, default 100
sizeoptionalnumberSize of the particles, 1 is the designed size
glowoptionalbooleanLight around the pointer, default true
Barrierefreiheit
Aus dem Quellcode der Component abgeleitet.
- Kommt ohne Client-State aus. Der Server schreibt sie vollständig, sie ist auch ohne JavaScript lesbar.
Bewegung
- Ohne Animationen, sie steht sofort ruhig da.
Quellcode
Die Datei, die aiw add in dein Projekt legt. Sie gehört danach dir.
Datei anzeigen, 100 Zeilen
'use client';
import { GLSL_NOISE, ShaderBackdrop, ShaderCanvas, type ShaderLayerProps } from '@/components/ui/webgl';
/*
* A field of glowing particles in several depth layers. Near layers are
* larger, softer and faster, far layers fine and slow, so the field reads as
* space. The pointer pushes the layers apart (parallax) and lights the
* particles around it. Each particle lives in its own grid cell, so the cost
* stays flat however many there are. Phones draw fewer layers.
*/
export interface ParticleFieldProps extends ShaderLayerProps {
/** Particles per layer, 1 is the designed density, 2 twice as many */
density?: number;
/** Depth layers on desktop, 2 to 6, default 5. Phones draw about half. */
layers?: number;
/** Direction of the drift in degrees, 90 rises, default 100 */
direction?: number;
/** Size of the particles, 1 is the designed size */
size?: number;
/** Light around the pointer, default true */
glow?: boolean;
}
const FRAG = `${GLSL_NOISE}
uniform float u_density;uniform float u_layers;uniform vec2 u_dir;uniform float u_size;uniform float u_glow;
void main(){
float m=min(u_res.x,u_res.y);
vec2 p=(gl_FragCoord.xy-.5*u_res)/m;
vec2 mp=(u_mouse-.5)*u_res/m;
float n=max(2.,floor(u_layers*mix(.5,1.,u_quality)+.5));
vec3 col=vec3(0.);float al=0.;
for(int i=0;i<6;i++){
float fi=float(i);if(fi>=n)break;
float d=fi/max(1.,n-1.);
float sc=mix(26.,7.,d)*u_density;
vec2 q=p*sc-u_dir*u_time*mix(.25,1.1,d)+vec2(fi*17.3,fi*9.1);
q+=(mp*mix(.15,1.2,d)*u_hover+vec2(0.,(u_scroll-.5)*mix(.6,3.,d)))*sc*.08;
vec2 id=floor(q),f=fract(q)-.5;
vec2 h=hash2(id+fi*31.);
if(h.x>mix(.55,.22,d))continue;
vec2 o=(h-.5)*.5;
float r=mix(.0016,.0075,d)*sc*u_size*(.6+.8*fract(h.y*7.31));
float tw=.65+.35*sin(u_time*(1.+h.x*3.)+h.y*40.);
float dist=length(f-o);
float blur=r*mix(.35,.9,d*d);
float edge=smoothstep(.5,.32,max(abs(f.x),abs(f.y)));
float dt=smoothstep(r+blur,r-blur*.6,dist)+exp(-dist*dist/(r*r*5.))*.3*edge;
vec2 wp=(id+.5+o)/sc;
float near=u_glow*u_hover*exp(-dot(wp-mp,wp-mp)*30.);
vec3 c=mix(u_c0,u_c3,(1.-h.y)*mix(.25,1.,u_dark))+near*.4*u_dark;
float a=dt*tw*mix(.5,1.,d)*(.7+near*1.4);
col+=c*a;al+=a;
}
float fade=mix(.7,1.,u_dark)*u_intensity;
al=clamp(al*fade,0.,1.);
col=col*fade;
gl_FragColor=vec4(min(col,vec3(1.)),al);
}`;
/** The still picture: three sizes of dots, small and dense, larger and sparse */
const FALLBACK = [
'radial-gradient(circle at 30% 40%, color-mix(in oklab, var(--primary) 70%, transparent) 0 2.5px, transparent 3.5px) 0 0 / 97px 83px',
'radial-gradient(circle at 60% 70%, color-mix(in oklab, var(--primary) 45%, var(--foreground) 10%) 0 1.5px, transparent 2.5px) 0 0 / 53px 61px',
'radial-gradient(circle at 20% 20%, color-mix(in oklab, var(--foreground) 30%, transparent) 0 1px, transparent 1.6px) 0 0 / 29px 31px',
].join(', ');
/**
* Glowing particles in depth behind any content. With children it renders a
* box, without children only the layer for a `relative` parent.
*/
export function ParticleField({ intensity = 1, speed = 1, colors, interactive = true, density = 1, layers = 5, direction = 100, size = 1, glow = true, fallback, scrim = 'center', scrimStrength, scrimColor, children, className, contentClassName, layerClassName }: ParticleFieldProps) {
const rad = (direction * Math.PI) / 180;
return (
<ShaderBackdrop
scrim={scrim}
scrimStrength={scrimStrength}
scrimColor={scrimColor}
className={className}
contentClassName={contentClassName}
layer={
<ShaderCanvas
fragment={FRAG}
colors={colors ?? ['var(--primary)', 'var(--primary)', 'var(--primary)', 'color-mix(in oklab, var(--primary) 50%, var(--foreground))']}
uniforms={{ u_density: density, u_layers: Math.min(6, Math.max(2, layers)), u_dir: [Math.round(Math.cos(rad) * 1000) / 1000 * 0.12, Math.round(Math.sin(rad) * 1000) / 1000 * 0.12], u_size: size, u_glow: glow ? 1 : 0 }}
speed={speed}
intensity={intensity}
maxDpr={1.5}
pointer={interactive}
fallback={fallback ?? FALLBACK}
mask="radial-gradient(ellipse 90% 85% at 50% 50%, #000 55%, transparent)"
className={layerClassName}
/>
}
>
{children}
</ShaderBackdrop>
);
}Häufige Fragen
Wie installiere ich Partikelfeld?
Mit aiw add @ai-website/particle-field. Der Befehl legt die Datei components/ui/particle-field.tsx in dein Projekt, der Code gehört danach dir. Mit dabei sind webgl. Weitere npm-Pakete braucht sie nicht.
Welche Varianten hat Partikelfeld?
4 Varianten, Hero mit Tiefe, Treibendes Band, Hervorgehobene Karte und Langsames Treiben hinter einem Call to Action.
Kann ein KI-Assistent Partikelfeld einbauen?
Ja. Über den MCP-Server der aiw CLI finden Claude, Cursor, GitHub Copilot, Windsurf, Codex und Gemini Partikelfeld mit aiw_components und installieren sie mit aiw_add @ai-website/particle-field.