Files
klz-cables.com/components/home/hero-webgl/TransmissionLines.tsx
Marc Mintel 82bb7240d5
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Failing after 3m48s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 4s
chore(workspace): add gitea repository url to all packages
2026-02-27 11:27:22 +01:00

60 lines
2.1 KiB
TypeScript

import React, { useMemo, useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import { SceneData, SceneEdge } from './Generator';
import * as THREE from 'three';
import { Line } from '@react-three/drei';
// A single CatmullRomCurve3 cable with particles moving along it
const Cable: React.FC<{ edge: SceneEdge }> = ({ edge }) => {
const points = useMemo(() => edge.path.map(p => new THREE.Vector3(p[0], p[1], p[2])), [edge.path]);
const curve = useMemo(() => new THREE.CatmullRomCurve3(points), [points]);
// We extract the line points for rendering the static line
const linePoints = useMemo(() => curve.getPoints(20), [curve]);
const linePositions = useMemo(() => linePoints.flatMap(p => [p.x, p.y, p.z]), [linePoints]);
const particleRef = useRef<THREE.Mesh>(null!);
const timeRef = useRef(Math.random()); // Random offset for particles
useFrame((state, delta) => {
if (!particleRef.current) return;
// Move particle along the curve. Speed based on edge type.
const speed = edge.type === 'transmission' ? 0.3 : 0.15;
timeRef.current = (timeRef.current + delta * speed) % 1;
const pos = curve.getPointAt(timeRef.current);
particleRef.current.position.copy(pos);
});
return (
<group>
{/* The actual cable. Underground cables can just be transparent or slightly visible */}
{edge.type === 'transmission' && (
<Line
points={linePoints}
color="#334155"
lineWidth={1.5}
/>
)}
{/* The glowing particle */}
<mesh ref={particleRef}>
<sphereGeometry args={[edge.type === 'transmission' ? 0.8 : 0.4, 8, 8]} />
<meshBasicMaterial color="#82ed20" transparent opacity={0.8} />
</mesh>
</group>
);
};
const TransmissionLines: React.FC<{ data: SceneData }> = ({ data }) => {
return (
<group>
{data.edges.map(edge => (
<Cable key={edge.id} edge={edge} />
))}
</group>
);
};
export default TransmissionLines;