33import { cn } from "@/lib/utils" ;
44import { useEffect , useRef , useState } from "react" ;
55
6+ const lerp = ( start : number , end : number , t : number ) => {
7+ return start + ( end - start ) * t ;
8+ } ;
9+
610export 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