1
+ class Circle {
2
+ constructor ( { origin, speed, color, angle, context } ) {
3
+ this . origin = origin
4
+ this . position = { ...this . origin }
5
+ this . color = color
6
+ this . speed = speed
7
+ this . angle = angle
8
+ this . context = context
9
+ this . renderCount = 0
10
+ }
11
+
12
+ draw ( ) {
13
+ this . context . fillStyle = this . color
14
+ this . context . beginPath ( )
15
+ this . context . arc ( this . position . x , this . position . y , 2 , 0 , Math . PI * 2 )
16
+ this . context . fill ( )
17
+ }
18
+
19
+ move ( ) {
20
+ this . position . x = ( Math . sin ( this . angle ) * this . speed ) + this . position . x
21
+ this . position . y = ( Math . cos ( this . angle ) * this . speed ) + this . position . y + ( this . renderCount * 0.3 )
22
+ this . renderCount ++
23
+ }
24
+ }
25
+
26
+ class Boom {
27
+ constructor ( { origin, context, circleCount = 16 , area } ) {
28
+ this . origin = origin
29
+ this . context = context
30
+ this . circleCount = circleCount
31
+ this . area = area
32
+ this . stop = false
33
+ this . circles = [ ]
34
+ }
35
+
36
+ randomArray ( range ) {
37
+ const length = range . length
38
+ const randomIndex = Math . floor ( length * Math . random ( ) )
39
+ return range [ randomIndex ]
40
+ }
41
+
42
+ randomColor ( ) {
43
+ const range = [ '8' , '9' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' ]
44
+ return '#' + this . randomArray ( range ) + this . randomArray ( range ) + this . randomArray ( range ) + this . randomArray ( range ) + this . randomArray ( range ) + this . randomArray ( range )
45
+ }
46
+
47
+ randomRange ( start , end ) {
48
+ return ( end - start ) * Math . random ( ) + start
49
+ }
50
+
51
+ init ( ) {
52
+ for ( let i = 0 ; i < this . circleCount ; i ++ ) {
53
+ const circle = new Circle ( {
54
+ context : this . context ,
55
+ origin : this . origin ,
56
+ color : this . randomColor ( ) ,
57
+ angle : this . randomRange ( Math . PI - 1 , Math . PI + 1 ) ,
58
+ speed : this . randomRange ( 1 , 6 )
59
+ } )
60
+ this . circles . push ( circle )
61
+ }
62
+ }
63
+
64
+ move ( ) {
65
+ this . circles . forEach ( ( circle , index ) => {
66
+ if ( circle . position . x > this . area . width || circle . position . y > this . area . height ) {
67
+ return this . circles . splice ( index , 1 )
68
+ }
69
+ circle . move ( )
70
+ } )
71
+ if ( this . circles . length == 0 ) {
72
+ this . stop = true
73
+ }
74
+ }
75
+
76
+ draw ( ) {
77
+ this . circles . forEach ( circle => circle . draw ( ) )
78
+ }
79
+ }
80
+
81
+ class CursorSpecialEffects {
82
+ constructor ( ) {
83
+ this . computerCanvas = document . createElement ( 'canvas' )
84
+ this . renderCanvas = document . createElement ( 'canvas' )
85
+
86
+ this . computerContext = this . computerCanvas . getContext ( '2d' )
87
+ this . renderContext = this . renderCanvas . getContext ( '2d' )
88
+
89
+ this . globalWidth = window . innerWidth
90
+ this . globalHeight = window . innerHeight
91
+
92
+ this . booms = [ ]
93
+ this . running = false
94
+ }
95
+
96
+ handleMouseDown ( e ) {
97
+ const boom = new Boom ( {
98
+ origin : { x : e . clientX , y : e . clientY } ,
99
+ context : this . computerContext ,
100
+ area : {
101
+ width : this . globalWidth ,
102
+ height : this . globalHeight
103
+ }
104
+ } )
105
+ boom . init ( )
106
+ this . booms . push ( boom )
107
+ this . running || this . run ( )
108
+ }
109
+
110
+ handlePageHide ( ) {
111
+ this . booms = [ ]
112
+ this . running = false
113
+ }
114
+
115
+ init ( ) {
116
+ const style = this . renderCanvas . style
117
+ style . position = 'fixed'
118
+ style . top = style . left = 0
119
+ style . zIndex = '999999999999999999999999999999999999999999'
120
+ style . pointerEvents = 'none'
121
+
122
+ style . width = this . renderCanvas . width = this . computerCanvas . width = this . globalWidth
123
+ style . height = this . renderCanvas . height = this . computerCanvas . height = this . globalHeight
124
+
125
+ document . body . append ( this . renderCanvas )
126
+
127
+ window . addEventListener ( 'mousedown' , this . handleMouseDown . bind ( this ) )
128
+ window . addEventListener ( 'pagehide' , this . handlePageHide . bind ( this ) )
129
+ }
130
+
131
+ run ( ) {
132
+ this . running = true
133
+ if ( this . booms . length == 0 ) {
134
+ return this . running = false
135
+ }
136
+
137
+ requestAnimationFrame ( this . run . bind ( this ) )
138
+
139
+ this . computerContext . clearRect ( 0 , 0 , this . globalWidth , this . globalHeight )
140
+ this . renderContext . clearRect ( 0 , 0 , this . globalWidth , this . globalHeight )
141
+
142
+ this . booms . forEach ( ( boom , index ) => {
143
+ if ( boom . stop ) {
144
+ return this . booms . splice ( index , 1 )
145
+ }
146
+ boom . move ( )
147
+ boom . draw ( )
148
+ } )
149
+ this . renderContext . drawImage ( this . computerCanvas , 0 , 0 , this . globalWidth , this . globalHeight )
150
+ }
151
+ }
152
+
153
+ const cursorSpecialEffects = new CursorSpecialEffects ( )
154
+ cursorSpecialEffects . init ( )
0 commit comments