Two glowing strands winding around each other in a slowly spinning double helix.
three @react-three/fiber @react-three/drei<Helix /> inside your own <Canvas>.import { useMemo, useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import * as THREE from 'three';
import type { Group } from 'three';
class HelixCurve extends THREE.Curve<THREE.Vector3> {
phase: number;
constructor(phase = 0) {
super();
this.phase = phase;
}
getPoint(t: number, target = new THREE.Vector3()) {
const a = this.phase + t * 3 * Math.PI * 2;
return target.set(Math.cos(a) * 0.7, (t - 0.5) * 2.6, Math.sin(a) * 0.7);
}
}
export default function Helix({ color = '#22e0ff', scale = 1 }: { color?: string; scale?: number }) {
const g = useRef<Group>(null);
const geoA = useMemo(() => new THREE.TubeGeometry(new HelixCurve(0), 220, 0.045, 12, false), []);
const geoB = useMemo(() => new THREE.TubeGeometry(new HelixCurve(Math.PI), 220, 0.045, 12, false), []);
useFrame((_, dt) => {
if (g.current) g.current.rotation.y += dt * 0.5;
});
return (
<group ref={g} scale={scale}>
<mesh geometry={geoA}>
<meshStandardMaterial color={color} emissive={color} emissiveIntensity={1.3} roughness={0.3} metalness={0.5} />
</mesh>
<mesh geometry={geoB}>
<meshStandardMaterial color="#ff2fd0" emissive="#ff2fd0" emissiveIntensity={1.3} roughness={0.3} metalness={0.5} />
</mesh>
</group>
);
}