← All elements

Hypno Rays

Abstract

Hundreds of fine colored rays bursting from a dark center, slowly turning.

Tip: pick a preset, use the custom picker, or paste your brand hex to preview this element in your colors. Some elements use a fixed multi-color palette.

Usage
Install: three @react-three/fiber @react-three/drei
Drop <HypnoRays /> inside your own <Canvas>.
Mood
Hypnotic, deep, kinetic. A tunnel of light.
Colors
Cyan, violet, magenta, and amber rays that fade to black at the center.
Motion
The whole burst rotates slowly like a spinning tunnel.
View component source
import { useMemo, useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import * as THREE from 'three';
import type { LineSegments } from 'three';

const RAYS = 220;

export default function HypnoRays({ scale = 1 }: { color?: string; scale?: number }) {
  const ref = useRef<LineSegments>(null);
  const { positions, colors } = useMemo(() => {
    const pos = new Float32Array(RAYS * 2 * 3);
    const col = new Float32Array(RAYS * 2 * 3);
    const pal = [
      new THREE.Color('#22e0ff'),
      new THREE.Color('#8a5cff'),
      new THREE.Color('#ff2fd0'),
      new THREE.Color('#ff8a3d'),
    ];
    for (let i = 0; i < RAYS; i++) {
      const a = (i / RAYS) * Math.PI * 2;
      const inner = 0.3;
      const outer = 5;
      pos.set([Math.cos(a) * inner, Math.sin(a) * inner, 0, Math.cos(a) * outer, Math.sin(a) * outer, 0], i * 6);
      const c = pal[i % pal.length];
      // dark at the center, bright at the rim
      col.set([c.r * 0.05, c.g * 0.05, c.b * 0.05, c.r, c.g, c.b], i * 6);
    }
    return { positions: pos, colors: col };
  }, []);
  useFrame((_, dt) => {
    if (ref.current) ref.current.rotation.z += dt * 0.05;
  });
  return (
    <lineSegments ref={ref} scale={scale}>
      <bufferGeometry>
        <bufferAttribute attach="attributes-position" args={[positions, 3]} />
        <bufferAttribute attach="attributes-color" args={[colors, 3]} />
      </bufferGeometry>
      <lineBasicMaterial
        vertexColors
        toneMapped={false}
        transparent
        opacity={0.9}
        blending={THREE.AdditiveBlending}
        depthWrite={false}
      />
    </lineSegments>
  );
}