An iridescent tube looping through a smooth lissajous path, tumbling in place.
three @react-three/fiber @react-three/drei<FlowRibbon /> inside your own <Canvas>.import { useMemo, useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import * as THREE from 'three';
import type { Mesh } from 'three';
class FlowCurve extends THREE.Curve<THREE.Vector3> {
getPoint(t: number, target = new THREE.Vector3()) {
const a = t * Math.PI * 2;
return target.set(Math.sin(a * 2) * 1.15, Math.sin(a * 3) * 0.85, Math.cos(a * 2) * 1.15);
}
}
export default function FlowRibbon({ color = '#8a5cff', scale = 1 }: { color?: string; scale?: number }) {
const ref = useRef<Mesh>(null);
const geo = useMemo(() => new THREE.TubeGeometry(new FlowCurve(), 260, 0.1, 20, true), []);
useFrame((_, dt) => {
if (!ref.current) return;
ref.current.rotation.y += dt * 0.3;
ref.current.rotation.x += dt * 0.12;
});
return (
<mesh ref={ref} geometry={geo} scale={scale}>
<meshPhysicalMaterial
color={color}
metalness={1}
roughness={0.12}
iridescence={1}
iridescenceIOR={1.4}
iridescenceThicknessRange={[120, 560]}
clearcoat={1}
emissive={color}
emissiveIntensity={0.15}
/>
</mesh>
);
}