Skip to content

Commit e0533f2

Browse files
committed
lerp animation
1 parent 469352e commit e0533f2

2 files changed

Lines changed: 54 additions & 31 deletions

File tree

app/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export default async function Home() {
3131
</section> */}
3232

3333
{/* Featured Post */}
34-
<section className="my-16">
34+
<section className="min-h-[90vh] py-16 justify-end flex flex-col">
3535
<h2 className="mb-8 text-zinc-900 dark:text-zinc-50">Artículo Destacado</h2>
3636
<div className="grid grid-cols-1 lg:grid-cols-5 gap-8">
3737
<div className="lg:col-span-3 space-y-4">
@@ -89,7 +89,7 @@ export default async function Home() {
8989
</section>
9090

9191
{/* Recent Posts */}
92-
<section>
92+
<section className="py-16">
9393
<h2 className="mb-8 text-zinc-900 dark:text-zinc-50">Artículos Recientes</h2>
9494
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
9595
{recentPosts.map((post) => (

components/ascii-animation.tsx

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,50 @@
33
import { cn } from "@/lib/utils";
44
import { useEffect, useRef, useState } from "react";
55

6+
const lerp = (start: number, end: number, t: number) => {
7+
return start + (end - start) * t;
8+
};
9+
610
export function AsciiAnimation({ className }: { className?: string }) {
711
const preRef = useRef<HTMLPreElement>(null);
8-
const [mousePosition, setMousePosition] = useState({ x: 0.5, y: 0 });
912
const animationFrameRef = useRef(0);
1013
const timeRef = useRef(0);
1114
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
15+
const [smoothPos, setSmoothPos] = useState({ x: 0, y: 0 });
16+
const targetPos = useRef({ x: 0, y: 0 });
17+
18+
useEffect(() => {
19+
const handleMouseMove = (e: MouseEvent) => {
20+
if (preRef.current) {
21+
const rect = preRef.current.getBoundingClientRect();
22+
targetPos.current = {
23+
x: (e.clientX - rect.left) / rect.width,
24+
y: (e.clientY - rect.top) / rect.height,
25+
};
26+
}
27+
};
28+
29+
window.addEventListener("mousemove", handleMouseMove);
30+
return () => window.removeEventListener("mousemove", handleMouseMove);
31+
}, []);
32+
33+
useEffect(() => {
34+
let animationFrameId: number;
35+
36+
const animate = () => {
37+
setSmoothPos((prev) => {
38+
const t = 0.01; // Smoothness factor — smaller = smoother
39+
return {
40+
x: lerp(prev.x, targetPos.current.x, t),
41+
y: lerp(prev.y, targetPos.current.y, t),
42+
};
43+
});
44+
animationFrameId = requestAnimationFrame(animate);
45+
};
46+
47+
animate();
48+
return () => cancelAnimationFrame(animationFrameId);
49+
}, []);
1250

1351
// Handle resize and calculate dimensions
1452
useEffect(() => {
@@ -35,31 +73,14 @@ export function AsciiAnimation({ className }: { className?: string }) {
3573
};
3674
}, []);
3775

38-
// Handle mouse movement
39-
useEffect(() => {
40-
const handleMouseMove = (e: MouseEvent) => {
41-
if (preRef.current) {
42-
const rect = preRef.current.getBoundingClientRect();
43-
setMousePosition({
44-
x: (e.clientX - rect.left) / rect.width,
45-
// y: (e.clientY - rect.top) / rect.height,
46-
y: 0,
47-
});
48-
}
49-
};
50-
51-
window.addEventListener("mousemove", handleMouseMove);
52-
return () => window.removeEventListener("mousemove", handleMouseMove);
53-
}, []);
54-
5576
// Animation loop
5677
useEffect(() => {
5778
if (dimensions.width === 0 || dimensions.height === 0) return;
5879

59-
const chars = " .,:;+*?%S#@";
80+
const chars = " .,:;+*?%$#@";
6081

6182
const animate = () => {
62-
timeRef.current += 0.03;
83+
timeRef.current += 0.005;
6384

6485
if (!preRef.current) return;
6586

@@ -72,8 +93,8 @@ export function AsciiAnimation({ className }: { className?: string }) {
7293
const ny = y / dimensions.height - 0.5;
7394

7495
// Distance from mouse position (normalized)
75-
const dx = nx - (mousePosition.x - 0.5);
76-
const dy = ny - (mousePosition.y - 0.5);
96+
const dx = nx - (smoothPos.x - 0.5);
97+
const dy = ny - (smoothPos.y - 0.5);
7798
const dist = Math.sqrt(dx * dx + dy * dy);
7899

79100
// Wave pattern
@@ -97,18 +118,20 @@ export function AsciiAnimation({ className }: { className?: string }) {
97118
return () => {
98119
cancelAnimationFrame(animationFrameRef.current);
99120
};
100-
}, [dimensions, mousePosition]);
121+
}, [dimensions, smoothPos]);
101122

102123
return (
103124
<div className={cn("flex items-center justify-center w-full h-screen mx-auto", className)}>
104125
<pre
105126
ref={preRef}
106-
className="w-full h-full p-0 m-0 overflow-hidden leading-[10px] font-mono opacity-[5%]"
107-
style={{
108-
fontSize: "1.5rem",
109-
fontFamily: "monospace",
110-
userSelect: "none",
111-
}}
127+
className="w-full h-full p-0 m-0 overflow-hidden font-extralight font-mono text-xl opacity-[15%]"
128+
style={
129+
{
130+
// fontSize: "1.5rem",
131+
// fontFamily: "monospace",
132+
// userSelect: "none",
133+
}
134+
}
112135
/>
113136
</div>
114137
);

0 commit comments

Comments
 (0)