94 lines
2.7 KiB
TypeScript
94 lines
2.7 KiB
TypeScript
'use client';
|
|
|
|
import { motion } from 'framer-motion';
|
|
|
|
interface HDDBoreAnimationProps {
|
|
className?: string;
|
|
invert?: boolean;
|
|
}
|
|
|
|
/**
|
|
* HDDBoreAnimation
|
|
*
|
|
* Visualizes Horizontal Directional Drilling (Spülbohren).
|
|
* 1. A segmented drill rod (Gestänge) pushes through a subterranean arc (Pilotbohrung).
|
|
* 2. It pulls back a thick, solid orange pipe (Rohreinzug).
|
|
*
|
|
* This directly ties to E-TIB's core services, visually representing the
|
|
* physical act of laying a conduit pipe under an obstacle.
|
|
*/
|
|
export function HDDBoreAnimation({ className = '', invert = false }: HDDBoreAnimationProps) {
|
|
// Track color
|
|
const color = invert ? '#0a3d28' : '#0e7a5c';
|
|
// Bright orange for the conduit pipe (Kabelschutzrohr)
|
|
const pipeColor = '#ff6b00';
|
|
|
|
// Parabolic path under an implied obstacle
|
|
const pathD = "M 50 100 C 300 100 400 250 600 250 C 800 250 900 100 1150 100";
|
|
// Length of this cubic bezier is approx 1300
|
|
const pathLen = 1300;
|
|
|
|
return (
|
|
<svg
|
|
viewBox="0 0 1200 300"
|
|
preserveAspectRatio="none"
|
|
className={`absolute pointer-events-none select-none w-full ${className}`}
|
|
aria-hidden="true"
|
|
>
|
|
{/* Planned path (subtle) */}
|
|
<path
|
|
d={pathD}
|
|
stroke={color}
|
|
strokeWidth="2"
|
|
strokeDasharray="5 15"
|
|
fill="none"
|
|
opacity={0.15}
|
|
/>
|
|
|
|
{/* Step 1: Drill Rod (Pilotbohrung) pushing Left -> Right */}
|
|
<motion.path
|
|
d={pathD}
|
|
stroke={color}
|
|
strokeWidth="4"
|
|
fill="none"
|
|
strokeLinecap="round"
|
|
// Segmented rod look (40px rod, 5px gap)
|
|
strokeDasharray={`40 5 ${pathLen}`}
|
|
animate={{
|
|
strokeDashoffset: [pathLen, 0, 0, 0, pathLen],
|
|
opacity: [0, 1, 1, 0, 0]
|
|
}}
|
|
transition={{
|
|
duration: 10,
|
|
repeat: Infinity,
|
|
ease: "easeInOut",
|
|
times: [0, 0.4, 0.45, 0.46, 1] // 0-4s: push, 4-4.5s: pause, 4.6s: vanish
|
|
}}
|
|
/>
|
|
|
|
{/* Step 2: Cable/Pipe Pullback (Rohreinzug) Right -> Left */}
|
|
<motion.path
|
|
d={pathD}
|
|
stroke={pipeColor}
|
|
strokeWidth="8"
|
|
fill="none"
|
|
strokeLinecap="round"
|
|
// Solid pipe
|
|
strokeDasharray={`${pathLen} ${pathLen}`}
|
|
animate={{
|
|
// Starts hidden at the right (offset = -pathLen)
|
|
// Pulls back to left (offset = 0)
|
|
strokeDashoffset: [-pathLen, -pathLen, 0, 0, -pathLen],
|
|
opacity: [0, 0, 1, 1, 0]
|
|
}}
|
|
transition={{
|
|
duration: 10,
|
|
repeat: Infinity,
|
|
ease: "easeInOut",
|
|
times: [0, 0.45, 0.85, 0.95, 1] // 0-4.5s: hidden, 4.5-8.5s: pull back, 8.5-9.5s: rest, 10s: reset
|
|
}}
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|