Lichtstrahlen als Hintergrund
Lichtschächte von oben mit Dunst und schwebendem Staub, mit WebGL gezeichnet. Sie schimmern, ohne sich zu wiederholen, die Quelle folgt leicht dem Zeiger.
Eine Bühne, von oben beleuchtet
Lichtstrahlen fallen von oben, mit Dunst und schwebendem Staub in den Strahlen, mit WebGL gezeichnet. Sie stellen eine Überschrift auf eine Bühne und lenken den Blick direkt dorthin, ein Schleier hält den Text dabei lesbar.
„Hero von oben“ lässt Licht gerade auf eine mittige Überschrift fallen, wie durch ein Oberlicht. Das „Morgenband“ lässt das Licht schräg von rechts oben über ein Band mit Kennzahlen fallen. Die „Karte im Rampenlicht“ beleuchtet mit einem schmalen Strahl die eine Karte, auf die es ankommt. „Hinter einem Call to Action“ öffnet einen weiten, langsamen Lichtfächer über der Abschlussfläche.
Strahlen wirken am besten mit einer kurzen, mittigen Überschrift genau dort, wo das Licht landet. Nimm die Karte im Rampenlicht für den Tarif oder das Feature, das du empfiehlst, der Strahl zeigt von selbst darauf.
Details
Was Lichtstrahlen 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/light-rays.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 LightRaysProps aus components/ui/light-rays.tsx. Beschreibungen stammen aus den Kommentaren im Code und sind auf Englisch. Nimmt außerdem alle Props von ShaderLayerProps an.
originoptionalLightRaysOrigintoptop-lefttop-right
Where the light comes from
reachoptionalnumberHow far the rays reach down, 0.3 to 1.5, default 1
spreadoptionalnumberOpening of the cone, 1 is the designed width
dustoptionalbooleanFloating dust in the light, 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, 111 Zeilen
'use client';
import { GLSL_NOISE, ShaderBackdrop, ShaderCanvas, type ShaderLayerProps } from '@/components/ui/webgl';
/*
* Shafts of light falling from above, like sun through a high window. The
* rays are noise along the angle around a source above the box, layered in
* three widths that drift at different paces, so they shimmer without ever
* repeating. A thin haze and slow floating dust give the light its volume.
* Soft by nature, rendered at reduced resolution.
*/
export type LightRaysOrigin = 'top' | 'top-left' | 'top-right';
export interface LightRaysProps extends ShaderLayerProps {
/** Where the light comes from */
origin?: LightRaysOrigin;
/** How far the rays reach down, 0.3 to 1.5, default 1 */
reach?: number;
/** Opening of the cone, 1 is the designed width */
spread?: number;
/** Floating dust in the light, default true */
dust?: boolean;
}
const ORIGIN: Record<LightRaysOrigin, number> = { 'top-left': -1, top: 0, 'top-right': 1 };
const FRAG = `${GLSL_NOISE}
uniform float u_origin;uniform float u_reach;uniform float u_spread;uniform float u_dust;
void main(){
float m=min(u_res.x,u_res.y);
vec2 p=(gl_FragCoord.xy-.5*u_res)/m;
float hw=.5*u_res.x/m,hh=.5*u_res.y/m;
vec2 src=vec2(u_origin*hw*.8+(u_mouse.x-.5)*.25*u_hover,hh+.35);
vec2 d=p-src;
float dist=length(d);
float ang=atan(d.x,-d.y);
float axis=-u_origin*.42;
float ca=(ang-axis)/(.62*u_spread);float cone=exp(-ca*ca);
float t=u_time;
float r=noise(vec2(ang*9./u_spread,t*.12))*.5+noise(vec2(ang*23./u_spread+3.,-t*.2))*.32+noise(vec2(ang*51./u_spread+7.,t*.35))*.18;
r=pow(smoothstep(.25,.95,r),1.6);
float len=hh*2.*u_reach+.3;
float fall=smoothstep(len,0.,dist-.35)*smoothstep(0.,.5,dist);
float haze=fbm(p*1.6+vec2(0.,t*.05))*.35;
float v=cone*fall*(r*.85+haze*.4+.06);
float dust=0.;
if(u_dust>.5){
vec2 q=p*14.+vec2(t*.15,-t*.25);
vec2 id=floor(q);vec2 h=hash2(id);
float dd=length(fract(q)-.5-(h-.5)*.6);
dust=smoothstep(.06,.0,dd)*step(.86,h.x)*(.5+.5*sin(t*2.+h.y*30.))*cone*fall*1.4;
}
vec3 col=mix(u_c0,u_c3,clamp(r*.7+(1.-dist/len)*.4,0.,1.)*u_dark);
float a=(v+dust)*mix(.5,1.,u_dark)*u_intensity;
a=clamp(a,0.,1.);
gl_FragColor=vec4(col*a,a);
}`;
const FALLBACK_AT: Record<LightRaysOrigin, string> = { top: '50% -12%', 'top-left': '12% -12%', 'top-right': '88% -12%' };
const FALLBACK_TURN: Record<LightRaysOrigin, number> = { top: 180, 'top-left': 156, 'top-right': 204 };
/** Still picture: a cone of striped light from the same corner */
function fallbackFor(origin: LightRaysOrigin) {
const at = FALLBACK_AT[origin];
const turn = FALLBACK_TURN[origin];
const ray = 'color-mix(in oklab, var(--primary) 40%, var(--foreground) 12%)';
return [
`repeating-conic-gradient(from ${turn - 40}deg at ${at}, transparent 0deg, color-mix(in oklab, ${ray} 30%, transparent) 2deg, transparent 5deg, transparent 9deg)`,
`radial-gradient(ellipse 60% 90% at ${at}, color-mix(in oklab, var(--primary) 26%, transparent), transparent 70%)`,
].join(', ');
}
/**
* Light rays from above behind any content. With children it renders a box,
* without children only the layer for a `relative` parent.
*/
export function LightRays({ intensity = 1, speed = 1, colors, interactive = true, origin = 'top', reach = 1, spread = 1, dust = true, fallback, scrim = 'none', scrimStrength, scrimColor, children, className, contentClassName, layerClassName }: LightRaysProps) {
const at = FALLBACK_AT[origin];
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) 35%, var(--foreground))']}
uniforms={{ u_origin: ORIGIN[origin], u_reach: reach, u_spread: spread, u_dust: dust ? 1 : 0 }}
speed={speed}
intensity={intensity}
scale={0.6}
pointer={interactive}
fallback={
fallback ?? (
<div
className="absolute inset-0"
style={{ background: fallbackFor(origin), maskImage: `radial-gradient(ellipse 90% 110% at ${at}, #000 20%, transparent 75%)`, WebkitMaskImage: `radial-gradient(ellipse 90% 110% at ${at}, #000 20%, transparent 75%)` }}
/>
)
}
className={layerClassName}
/>
}
>
{children}
</ShaderBackdrop>
);
}Häufige Fragen
Wie installiere ich Lichtstrahlen?
Mit aiw add @ai-website/light-rays. Der Befehl legt die Datei components/ui/light-rays.tsx in dein Projekt, der Code gehört danach dir. Mit dabei sind webgl. Weitere npm-Pakete braucht sie nicht.
Welche Varianten hat Lichtstrahlen?
4 Varianten, Hero von oben, Morgenband, Karte im Rampenlicht und Hinter einem Call to Action.
Kann ein KI-Assistent Lichtstrahlen einbauen?
Ja. Über den MCP-Server der aiw CLI finden Claude, Cursor, GitHub Copilot, Windsurf, Codex und Gemini Lichtstrahlen mit aiw_components und installieren sie mit aiw_add @ai-website/light-rays.