import { useEffect, useRef } from "react";
export default function AnimatedD() {
const canvasRef = useRef(null);
const frameRef = useRef(0);
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
const W = canvas.width = 612;
const H = canvas.height = 612;
const totalLines = 48;
const lineSpacing = H / (totalLines + 2);
// Define the D shape as a clip path using bezier curves
function getDPath(cx, cy, w, h) {
const left = cx - w * 0.38;
const right = cx + w * 0.38;
const top = cy - h * 0.44;
const bottom = cy + h * 0.44;
return { left, right, top, bottom, cx, cy, w, h };
}
function isInsideD(x, y, d) {
// Outer D boundary
const { left, right, top, bottom, cx, cy } = d;
// Left vertical bar region
const barRight = left + d.w * 0.22;
const inLeftBar = x >= left && x <= barRight && y >= top && y <= bottom;
// Curved right part — approximate with ellipse
const ellipseCx = left + d.w * 0.1;
const ellipseRx = right - ellipseCx;
const ellipseRy = (bottom - top) / 2;
const ellipseCy = cy;
const nx = (x - ellipseCx) / ellipseRx;
const ny = (y - ellipseCy) / ellipseRy;
const inOuter = nx * nx + ny * ny <= 1;
// Inner cutout (the hollow of the D)
const innerLeft = barRight + d.w * 0.04;
const innerRx = right - innerLeft - d.w * 0.08;
const innerRy = ellipseRy * 0.62;
const innerCx = innerLeft;
const inx = (x - innerCx) / innerRx;
const iny = (y - ellipseCy) / innerRy;
const inInner = inx >= 0 && inx * inx + iny * iny <= 1;
return (inLeftBar || inOuter) && !inInner;
}
let t = 0;
function draw() {
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, W, H);
const d = getDPath(W / 2, H / 2, W * 0.72, H * 0.82);
ctx.strokeStyle = "#fff";
ctx.lineWidth = 2.6;
ctx.lineCap = "round";
for (let i = 1; i <= totalLines; i++) {
const y = i * lineSpacing + lineSpacing * 0.5;
ctx.beginPath();
let firstPoint = true;
const step = 3;
for (let x = 0; x <= W; x += step) {
if (isInsideD(x, y, d)) {
// Wave distortion
const wave =
Math.sin(x * 0.022 + t + i * 0.3) * 5 +
Math.sin(x * 0.011 - t * 1.3 + i * 0.15) * 3.5 +
Math.sin(x * 0.044 + t * 0.7) * 1.5;
const wy = y + wave;
if (firstPoint) {
ctx.moveTo(x, wy);
firstPoint = false;
} else {
ctx.lineTo(x, wy);
}
} else {
if (!firstPoint) {
ctx.stroke();
ctx.beginPath();
firstPoint = true;
}
}
}
ctx.stroke();
}
t += 0.025;
frameRef.current = requestAnimationFrame(draw);
}
draw();
return () => cancelAnimationFrame(frameRef.current);
}, []);
return (
);
}