1- $ ( '#parallax' ) . parallax ( {
2- invertX : true ,
3- invertY : true ,
4- scalarX : 15 ,
5- frictionY : .1
6- } ) ;
7-
8-
9- particlesJS ( "particles-js" , {
10- "particles" : {
11- "number" : {
12- "value" : 120 ,
13- "density" : {
14- "enable" : true ,
15- "value_area" : 800
16- }
17- } ,
18- "color" : {
19- "value" : "#ffffff"
20- } ,
21- "shape" : {
22- "type" : "circle" ,
23- "stroke" : {
24- "width" : 0 ,
25- "color" : "#000000"
26- } ,
27- "polygon" : {
28- "nb_sides" : 5
29- } ,
30- "image" : {
31- "src" : "img/github.svg" ,
32- "width" : 100 ,
33- "height" : 100
34- }
35- } ,
36- "opacity" : {
37- "value" : 0.5 ,
38- "random" : false ,
39- "anim" : {
40- "enable" : false ,
41- "speed" : 1 ,
42- "opacity_min" : 0.1 ,
43- "sync" : false
44- }
45- } ,
46- "size" : {
47- "value" : 3 ,
48- "random" : true ,
49- "anim" : {
50- "enable" : false ,
51- "speed" : 40 ,
52- "size_min" : 0.1 ,
53- "sync" : false
54- }
55- } ,
56- "line_linked" : {
57- "enable" : true ,
58- "distance" : 150 ,
59- "color" : "#ffffff" ,
60- "opacity" : 0.4 ,
61- "width" : 1
62- } ,
63- "move" : {
64- "enable" : true ,
65- "speed" : 6 ,
66- "direction" : "none" ,
67- "random" : false ,
68- "straight" : false ,
69- "out_mode" : "out" ,
70- "bounce" : false ,
71- "attract" : {
72- "enable" : false ,
73- "rotateX" : 600 ,
74- "rotateY" : 1200
75- }
76- }
77- } ,
78- "interactivity" : {
79- "detect_on" : "canvas" ,
80- "events" : {
81- "onhover" : {
82- "enable" : true ,
83- "mode" : "grab"
84- } ,
85- "onclick" : {
86- "enable" : true ,
87- "mode" : "push"
88- } ,
89- "resize" : true
90- } ,
91- "modes" : {
92- "grab" : {
93- "distance" : 140 ,
94- "line_linked" : {
95- "opacity" : 1
96- }
97- } ,
98- "bubble" : {
99- "distance" : 400 ,
100- "size" : 40 ,
101- "duration" : 2 ,
102- "opacity" : 8 ,
103- "speed" : 3
104- } ,
105- "repulse" : {
106- "distance" : 200 ,
107- "duration" : 0.4
108- } ,
109- "push" : {
110- "particles_nb" : 4
111- } ,
112- "remove" : {
113- "particles_nb" : 2
114- }
115- }
116- } ,
117- "retina_detect" : true
118- } ) ;
119-
120-
1+ document . querySelectorAll ( '.button' ) . forEach ( button => {
2+
3+ let duration = 3000 ,
4+ svg = button . querySelector ( 'svg' ) ,
5+ svgPath = new Proxy ( {
6+ y : null ,
7+ smoothing : null
8+ } , {
9+ set ( target , key , value ) {
10+ target [ key ] = value ;
11+ if ( target . y !== null && target . smoothing !== null ) {
12+ svg . innerHTML = getPath ( target . y , target . smoothing , null ) ;
13+ }
14+ return true ;
15+ } ,
16+ get ( target , key ) {
17+ return target [ key ] ;
18+ }
19+ } ) ;
20+
21+ button . style . setProperty ( '--duration' , duration ) ;
22+
23+ svgPath . y = 20 ;
24+ svgPath . smoothing = 0 ;
25+
26+ button . addEventListener ( 'click' , e => {
27+
28+ e . preventDefault ( ) ;
29+
30+ if ( ! button . classList . contains ( 'loading' ) ) {
31+
32+ button . classList . add ( 'loading' ) ;
33+
34+ gsap . to ( svgPath , {
35+ smoothing : .3 ,
36+ duration : duration * .065 / 1000
37+ } ) ;
38+
39+ gsap . to ( svgPath , {
40+ y : 12 ,
41+ duration : duration * .265 / 1000 ,
42+ delay : duration * .065 / 1000 ,
43+ ease : Elastic . easeOut . config ( 1.12 , .4 )
44+ } ) ;
45+
46+ setTimeout ( ( ) => {
47+ svg . innerHTML = getPath ( 0 , 0 , [
48+ [ 3 , 14 ] ,
49+ [ 8 , 19 ] ,
50+ [ 21 , 6 ]
51+ ] ) ;
52+ } , duration / 2 ) ;
53+
54+ }
55+
56+ } ) ;
57+
58+ } ) ;
59+
60+ function getPoint ( point , i , a , smoothing ) {
61+ let cp = ( current , previous , next , reverse ) => {
62+ let p = previous || current ,
63+ n = next || current ,
64+ o = {
65+ length : Math . sqrt ( Math . pow ( n [ 0 ] - p [ 0 ] , 2 ) + Math . pow ( n [ 1 ] - p [ 1 ] , 2 ) ) ,
66+ angle : Math . atan2 ( n [ 1 ] - p [ 1 ] , n [ 0 ] - p [ 0 ] )
67+ } ,
68+ angle = o . angle + ( reverse ? Math . PI : 0 ) ,
69+ length = o . length * smoothing ;
70+ return [ current [ 0 ] + Math . cos ( angle ) * length , current [ 1 ] + Math . sin ( angle ) * length ] ;
71+ } ,
72+ cps = cp ( a [ i - 1 ] , a [ i - 2 ] , point , false ) ,
73+ cpe = cp ( point , a [ i - 1 ] , a [ i + 1 ] , true ) ;
74+ return `C ${ cps [ 0 ] } ,${ cps [ 1 ] } ${ cpe [ 0 ] } ,${ cpe [ 1 ] } ${ point [ 0 ] } ,${ point [ 1 ] } ` ;
75+ }
76+
77+ function getPath ( update , smoothing , pointsNew ) {
78+ let points = pointsNew ? pointsNew : [
79+ [ 4 , 12 ] ,
80+ [ 12 , update ] ,
81+ [ 20 , 12 ]
82+ ] ,
83+ d = points . reduce ( ( acc , point , i , a ) => i === 0 ? `M ${ point [ 0 ] } ,${ point [ 1 ] } ` : `${ acc } ${ getPoint ( point , i , a , smoothing ) } ` , '' ) ;
84+ return `<path d="${ d } " />` ;
85+ }
0 commit comments