1 const PARAMS = {
2 segments : 100 ,
3 stiffness : 0.1 ,
4 } ;
5
6 const svg = document . querySelector ( "svg.trail" ) ;
7 const path = svg ?. querySelector ( "path" ) ;
8
9 let points = [ ] ;
10 let mouse = { } ;
11
12 const move = ( event ) => {
13 const x = event . clientX ;
14 const y = event . clientY ;
15
16 mouse . x = x ;
17 mouse . y = y ;
18
19 if ( points . length === 0 ) {
20 for ( let i = 0 ; i < PARAMS . segments ; i ++ ) {
21 points . push ( {
22 x : mouse . x ,
23 y : mouse . y ,
24 } ) ;
25 }
26 }
27 } ;
28
29 const loop = ( ) => {
30 let px = mouse . x ;
31 let py = mouse . y ;
32
33 points . forEach ( ( p , index ) => {
34 p . x = px ;
35 p . y = py ;
36
37 let n = points [ index + 1 ] ;
38
39 if ( n ) {
40 px = px - ( p . x - n . x ) * PARAMS . stiffness ;
41 py = py - ( p . y - n . y ) * PARAMS . stiffness ;
42 }
43 } ) ;
44
45 points . length &&
46 path ?. setAttribute (
47 "d" ,
48 ` M ${ points . map ( ( p ) => ` ${ p . x } ${ p . y } ` ) . join ( ` L ` ) } M ${ mouse . x } ${ mouse . y } ` ,
49 ) ;
50
51 requestAnimationFrame ( loop ) ;
52 } ;
53
54 const resize = ( ) => {
55 const ww = window . innerWidth ;
56 const wh = window . innerHeight ;
57
58 svg . style . width = ww + "px" ;
59 svg . style . height = wh + "px" ;
60 svg . setAttribute ( "viewBox" , ` 0 0 ${ ww } ${ wh } ` ) ;
61 } ;
62
63 document . addEventListener ( "mousemove" , move ) ;
64 window . addEventListener ( "resize" , resize ) ;
65
66 loop ( ) ;
67 resize ( ) ;
Copy