valaxy-theme-hairy 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. package/LICENSE +21 -21
  2. package/client/index.ts +1 -1
  3. package/components/HairyBody.vue +49 -49
  4. package/components/HairyCodepen.vue +40 -40
  5. package/components/HairyComment.vue +33 -33
  6. package/components/HairyContainer.vue +17 -17
  7. package/components/HairyDrawer.vue +44 -44
  8. package/components/HairyFooter.vue +62 -62
  9. package/components/HairyHeader.vue +32 -32
  10. package/components/HairyImage.vue +15 -15
  11. package/components/HairyImageGroup.vue +65 -65
  12. package/components/HairyNavbar.vue +56 -56
  13. package/components/HairyPageArchives.vue +59 -59
  14. package/components/HairyPageTags.vue +48 -48
  15. package/components/HairyPosts.vue +54 -54
  16. package/components/HairySearch.vue +201 -201
  17. package/components/HairySidebar.vue +30 -30
  18. package/components/HairyTabbar.vue +56 -56
  19. package/components/PageTags.vue +48 -48
  20. package/components/ValaxyMain.vue +45 -45
  21. package/components/navbar/HairyNav.vue +16 -16
  22. package/components/navbar/HairyNavExpand.vue +12 -12
  23. package/components/navbar/HairyNavItem.vue +35 -35
  24. package/components/navbar/HairyNavbarBackground.vue +7 -7
  25. package/components/navbar/HairyNavbarSearch.vue +8 -8
  26. package/components/navbar/HairyNavbarTitle.vue +15 -15
  27. package/components/navbar/HairyNavbarToggleDark.vue +22 -22
  28. package/components/parts/HairyBreadcrumb.vue +51 -51
  29. package/components/parts/HairyBreadcrumbItem.vue +11 -11
  30. package/components/parts/HairyFootFish.js +352 -352
  31. package/components/parts/HairyFootFish.vue +38 -38
  32. package/components/parts/HairyHeadHero.vue +34 -34
  33. package/components/parts/HairyHeadWaves.vue +67 -67
  34. package/components/parts/HairyImageGlobal.vue +51 -51
  35. package/components/parts/HairyImageViewer.vue +23 -23
  36. package/components/parts/HairyLink.vue +21 -21
  37. package/components/parts/HairyMenu.vue +16 -16
  38. package/components/parts/HairyMenuItem.vue +47 -47
  39. package/components/parts/HairyOutline.vue +99 -99
  40. package/components/parts/HairyOutlineItem.vue +48 -48
  41. package/components/parts/HairySocialLinks.vue +27 -27
  42. package/components/parts/HairyTimelineContent.vue +39 -39
  43. package/components/parts/HairyUserNav.vue +95 -95
  44. package/components/parts/HairyUserStats.vue +18 -18
  45. package/components/posts/HairyArticleImage.vue +126 -126
  46. package/components/posts/HairyArticleSeries.vue +89 -89
  47. package/components/posts/HairyArticleText.vue +43 -43
  48. package/components/posts/HairyPostFooter.vue +15 -15
  49. package/components/posts/HairyPostImageList.vue +27 -27
  50. package/components/posts/HairyPostTextsList.vue +22 -22
  51. package/components/posts/HairyPostToggleLayout.vue +36 -36
  52. package/components/third/HairyAlgoliaSearch.vue +17 -17
  53. package/components/third/HairyFuseSearch.vue +10 -10
  54. package/components/third/HairyFuseSearchDialog.vue +32 -32
  55. package/components/third/HairyFuseSearchDropdown.vue +77 -77
  56. package/components/third/HairyFuseSearchFooter.vue +28 -28
  57. package/components/third/HairyFuseSearchHeader.vue +30 -30
  58. package/components/third/HairyFuseSearchHit.vue +52 -52
  59. package/components/third/HairySearchBtnDisplay.vue +29 -29
  60. package/components/third/HairySearchBtnInput.vue +20 -20
  61. package/components/third/HairySearchBtnKeys.vue +19 -19
  62. package/components/third/HairySwiperCarousel.vue +45 -45
  63. package/composables/archives.ts +48 -48
  64. package/composables/category.ts +43 -43
  65. package/composables/config.ts +11 -11
  66. package/composables/dark.ts +13 -13
  67. package/composables/fuse.ts +60 -60
  68. package/composables/index.ts +7 -7
  69. package/composables/layout.ts +16 -16
  70. package/composables/outline.ts +49 -49
  71. package/composables/tags.ts +36 -36
  72. package/layouts/archive-month.vue +13 -13
  73. package/layouts/archive-year.vue +13 -13
  74. package/layouts/archives.vue +11 -11
  75. package/layouts/categories.vue +13 -13
  76. package/layouts/default.vue +13 -15
  77. package/layouts/home.vue +33 -33
  78. package/layouts/post.vue +54 -54
  79. package/layouts/tag.vue +10 -10
  80. package/layouts/tags.vue +10 -14
  81. package/library/loading.scss +535 -535
  82. package/library/loading.ts +60 -60
  83. package/library/scroll.ts +22 -22
  84. package/locales/en.yml +1 -1
  85. package/locales/zh-CN.yml +1 -1
  86. package/node/images/default.json +139 -139
  87. package/node/images/index.ts +46 -46
  88. package/node/images/shims.d.ts +8 -8
  89. package/node/index.ts +2 -2
  90. package/node/theme/index.ts +78 -78
  91. package/package.json +1 -1
  92. package/pages/archives/[year]/[month]/index.vue +48 -48
  93. package/pages/archives/[year]/index.vue +73 -73
  94. package/pages/archives/index.md +6 -0
  95. package/pages/categories/[...its].vue +108 -108
  96. package/pages/index.vue +8 -8
  97. package/pages/page/[page].vue +12 -12
  98. package/pages/tags/[tag]/index.vue +38 -38
  99. package/pages/tags/index.md +7 -0
  100. package/setup/main.ts +9 -9
  101. package/store/index.ts +1 -1
  102. package/store/modules/global.ts +12 -12
  103. package/styles/components/aplayer.scss +75 -75
  104. package/styles/components/index.scss +3 -3
  105. package/styles/components/markdown.scss +89 -89
  106. package/styles/components/nprogress.scss +15 -15
  107. package/styles/components/scrollbar.scss +25 -25
  108. package/styles/css-vars.scss +171 -171
  109. package/styles/element-plus/index.scss +1 -1
  110. package/styles/element-plus/tabs.scss +25 -25
  111. package/styles/element-plus/timeline.scss +18 -18
  112. package/styles/font-face.scss +19 -19
  113. package/styles/global.scss +38 -38
  114. package/styles/index.scss +3 -3
  115. package/tsconfig.json +27 -27
  116. package/types/index.d.ts +163 -163
  117. package/unocss.config.ts +43 -43
  118. package/utils/index.ts +37 -37
  119. package/valaxy.config.ts +26 -26
  120. package/pages/archives/index.vue +0 -6
  121. package/pages/tags/index.vue +0 -6
@@ -1,352 +1,352 @@
1
- /* eslint-disable ts/no-use-before-define */
2
- /* eslint-disable eqeqeq */
3
-
4
- class RENDERER {
5
- ENABLE = false
6
- POINT_INTERVAL = 5
7
- FISH_COUNT = 3
8
- MAX_INTERVAL_COUNT = 50
9
- INIT_HEIGHT_RATE = 0.5
10
- THRESHOLD = 50
11
-
12
- COLOR = 'hsl(0, 0%, 95%)'
13
-
14
- constructor(color) {
15
- if (this.ENABLE)
16
- return
17
-
18
- this.setColor(color)
19
- this.removeCanvas()
20
- this.setParameters()
21
- this.reconstructMethods()
22
- this.setup()
23
- this.bindEvent()
24
- this.render()
25
- this.ENABLE = true
26
- }
27
-
28
- removeCanvas() {
29
- const container = document.querySelector('#jsi-flying-fish-container')
30
- const canvas = container.querySelector('canvas')
31
- if (canvas)
32
- canvas.remove()
33
- }
34
-
35
- setColor(color) {
36
- if (color)
37
- this.COLOR = color
38
- }
39
-
40
- setParameters() {
41
- this.$window = $(window)
42
- this.$container = $('#jsi-flying-fish-container')
43
- this.$canvas = $('<canvas />')
44
- this.context = this.$canvas.appendTo(this.$container).get(0).getContext('2d')
45
- this.points = []
46
- this.fishes = []
47
- this.watchIds = []
48
- }
49
-
50
- createSurfacePoints() {
51
- const count = Math.round(this.width / this.POINT_INTERVAL)
52
- this.pointInterval = this.width / (count - 1)
53
- this.points.push(new SURFACE_POINT(this, 0))
54
- for (let i = 1; i < count; i++) {
55
- const point = new SURFACE_POINT(this, i * this.pointInterval)
56
- const previous = this.points[i - 1]
57
- point.setPreviousPoint(previous)
58
- previous.setNextPoint(point)
59
- this.points.push(point)
60
- }
61
- }
62
-
63
- reconstructMethods() {
64
- this.watchWindowSize = this.watchWindowSize.bind(this)
65
- this.jdugeToStopResize = this.jdugeToStopResize.bind(this)
66
- this.startEpicenter = this.startEpicenter.bind(this)
67
- this.moveEpicenter = this.moveEpicenter.bind(this)
68
- this.reverseVertical = this.reverseVertical.bind(this)
69
- this.render = this.render.bind(this)
70
- }
71
-
72
- setup() {
73
- this.points.length = 0
74
- this.fishes.length = 0
75
- this.watchIds.length = 0
76
- this.intervalCount = this.MAX_INTERVAL_COUNT
77
- this.width = this.$container.width()
78
- this.height = this.$container.height()
79
- this.fishCount = (((this.FISH_COUNT * this.width) / 500) * this.height) / 500
80
- this.$canvas.attr({ width: this.width, height: this.height })
81
- this.reverse = false
82
- this.fishes.push(new FISH(this))
83
- this.createSurfacePoints()
84
- }
85
-
86
- watchWindowSize() {
87
- this.clearTimer()
88
- this.tmpWidth = this.$window.width()
89
- this.tmpHeight = this.$window.height()
90
- this.watchIds.push(setTimeout(this.jdugeToStopResize, this.WATCH_INTERVAL))
91
- }
92
-
93
- clearTimer() {
94
- while (this.watchIds.length > 0)
95
- clearTimeout(this.watchIds.pop())
96
- }
97
-
98
- jdugeToStopResize() {
99
- const width = this.$window.width()
100
- const height = this.$window.height()
101
- const stopped = width == this.tmpWidth && height == this.tmpHeight
102
- this.tmpWidth = width
103
- this.tmpHeight = height
104
- if (stopped)
105
- this.setup()
106
- }
107
-
108
- bindEvent() {
109
- this.$window.on('resize', this.watchWindowSize)
110
- this.$container.on('mouseenter', this.startEpicenter)
111
- this.$container.on('mousemove', this.moveEpicenter)
112
- }
113
-
114
- getAxis(event) {
115
- const offset = this.$container.offset()
116
- return { x: event.clientX - offset.left + this.$window.scrollLeft(), y: event.clientY - offset.top + this.$window.scrollTop() }
117
- }
118
-
119
- startEpicenter(event) {
120
- this.axis = this.getAxis(event)
121
- }
122
-
123
- moveEpicenter(event) {
124
- const axis = this.getAxis(event)
125
- if (!this.axis)
126
- this.axis = axis
127
-
128
- this.generateEpicenter(axis.x, axis.y, axis.y - this.axis.y)
129
- this.axis = axis
130
- }
131
-
132
- generateEpicenter(x, y, velocity) {
133
- if (y < this.height / 2 - this.THRESHOLD || y > this.height / 2 + this.THRESHOLD)
134
- return
135
-
136
- const index = Math.round(x / this.pointInterval)
137
- if (index < 0 || index >= this.points.length)
138
- return
139
-
140
- if (this.points[index])
141
- this.points[index].interfere(y, velocity)
142
- }
143
-
144
- reverseVertical() {
145
- this.reverse = !this.reverse
146
- for (let i = 0, count = this.fishes.length; i < count; i++)
147
- this.fishes[i].reverseVertical()
148
- }
149
-
150
- controlStatus() {
151
- for (let i = 0, count = this.points.length; i < count; i++)
152
- this.points[i].updateSelf()
153
-
154
- for (let i = 0, count = this.points.length; i < count; i++)
155
- this.points[i].updateNeighbors()
156
-
157
- if (this.fishes.length < this.fishCount && --this.intervalCount == 0) {
158
- this.intervalCount = this.MAX_INTERVAL_COUNT
159
- this.fishes.push(new FISH(this))
160
- }
161
- }
162
-
163
- render() {
164
- requestAnimationFrame(this.render)
165
- this.controlStatus()
166
- this.context.clearRect(0, 0, this.width, this.height)
167
- this.context.fillStyle = this.COLOR
168
- for (let i = 0, count = this.fishes.length; i < count; i++)
169
- this.fishes[i].render(this.context)
170
-
171
- this.context.save()
172
- this.context.globalCompositeOperation = 'xor'
173
- this.context.beginPath()
174
- this.context.moveTo(0, this.reverse ? 0 : this.height)
175
- for (let i = 0, count = this.points.length; i < count; i++)
176
- this.points[i].render(this.context)
177
-
178
- this.context.lineTo(this.width, this.reverse ? 0 : this.height)
179
- this.context.closePath()
180
- this.context.fill()
181
- this.context.restore()
182
- }
183
- }
184
-
185
- const SURFACE_POINT = function (renderer, x) {
186
- this.renderer = renderer
187
- this.x = x
188
- this.init()
189
- }
190
-
191
- SURFACE_POINT.prototype = {
192
- SPRING_CONSTANT: 0.03,
193
- SPRING_FRICTION: 0.9,
194
- WAVE_SPREAD: 0.3,
195
- ACCELARATION_RATE: 0.01,
196
- init() {
197
- this.initHeight = this.renderer.height * this.renderer.INIT_HEIGHT_RATE
198
- this.height = this.initHeight
199
- this.fy = 0
200
- this.force = { previous: 0, next: 0 }
201
- },
202
- setPreviousPoint(previous) {
203
- this.previous = previous
204
- },
205
- setNextPoint(next) {
206
- this.next = next
207
- },
208
- interfere(y, velocity) {
209
- this.fy = this.renderer.height * this.ACCELARATION_RATE * (this.renderer.height - this.height - y >= 0 ? -1 : 1) * Math.abs(velocity)
210
- },
211
- updateSelf() {
212
- this.fy += this.SPRING_CONSTANT * (this.initHeight - this.height)
213
- this.fy *= this.SPRING_FRICTION
214
- this.height += this.fy
215
- },
216
- updateNeighbors() {
217
- if (this.previous)
218
- this.force.previous = this.WAVE_SPREAD * (this.height - this.previous.height)
219
-
220
- if (this.next)
221
- this.force.next = this.WAVE_SPREAD * (this.height - this.next.height)
222
- },
223
- render(context) {
224
- if (this.previous) {
225
- this.previous.height += this.force.previous
226
- this.previous.fy += this.force.previous
227
- }
228
- if (this.next) {
229
- this.next.height += this.force.next
230
- this.next.fy += this.force.next
231
- }
232
- context.lineTo(this.x, this.renderer.height - this.height)
233
- },
234
- }
235
-
236
- const FISH = function (renderer) {
237
- this.renderer = renderer
238
- this.init()
239
- }
240
-
241
- FISH.prototype = {
242
- GRAVITY: 0.4,
243
- init() {
244
- this.direction = Math.random() < 0.5
245
- this.x = this.direction ? this.renderer.width + this.renderer.THRESHOLD : -this.renderer.THRESHOLD
246
- this.previousY = this.y
247
- this.vx = this.getRandomValue(4, 7) * (this.direction ? -1 : 1)
248
-
249
- if (this.renderer.reverse) {
250
- this.y = this.getRandomValue((this.renderer.height * 1) / 10, (this.renderer.height * 4) / 10)
251
- this.vy = this.getRandomValue(2, 5)
252
- this.ay = this.getRandomValue(0.05, 0.2)
253
- }
254
- else {
255
- this.y = this.getRandomValue((this.renderer.height * 6) / 10, (this.renderer.height * 9) / 10)
256
- this.vy = this.getRandomValue(-5, -2)
257
- this.ay = this.getRandomValue(-0.2, -0.05)
258
- }
259
- this.isOut = false
260
- this.theta = 0
261
- this.phi = 0
262
- },
263
- getRandomValue(min, max) {
264
- return min + (max - min) * Math.random()
265
- },
266
- reverseVertical() {
267
- this.isOut = !this.isOut
268
- this.ay *= -1
269
- },
270
- controlStatus() {
271
- this.previousY = this.y
272
- this.x += this.vx
273
- this.y += this.vy
274
- this.vy += this.ay
275
- if (this.renderer.reverse) {
276
- if (this.y > this.renderer.height * this.renderer.INIT_HEIGHT_RATE) {
277
- this.vy -= this.GRAVITY
278
- this.isOut = true
279
- }
280
- else {
281
- if (this.isOut)
282
- this.ay = this.getRandomValue(0.05, 0.2)
283
-
284
- this.isOut = false
285
- }
286
- }
287
- else {
288
- if (this.y < this.renderer.height * this.renderer.INIT_HEIGHT_RATE) {
289
- this.vy += this.GRAVITY
290
- this.isOut = true
291
- }
292
- else {
293
- if (this.isOut)
294
- this.ay = this.getRandomValue(-0.2, -0.05)
295
-
296
- this.isOut = false
297
- }
298
- }
299
- if (!this.isOut) {
300
- this.theta += Math.PI / 20
301
- this.theta %= Math.PI * 2
302
- this.phi += Math.PI / 30
303
- this.phi %= Math.PI * 2
304
- }
305
- this.renderer.generateEpicenter(this.x + (this.direction ? -1 : 1) * this.renderer.THRESHOLD, this.y, this.y - this.previousY)
306
- if ((this.vx > 0 && this.x > this.renderer.width + this.renderer.THRESHOLD) || (this.vx < 0 && this.x < -this.renderer.THRESHOLD))
307
- this.init()
308
- },
309
- render(context) {
310
- context.save()
311
- context.translate(this.x, this.y)
312
- context.rotate(Math.PI + Math.atan2(this.vy, this.vx))
313
- context.scale(1, this.direction ? 1 : -1)
314
- context.beginPath()
315
- context.moveTo(-30, 0)
316
- context.bezierCurveTo(-20, 15, 15, 10, 40, 0)
317
- context.bezierCurveTo(15, -10, -20, -15, -30, 0)
318
- context.fill()
319
- context.save()
320
- context.translate(40, 0)
321
- context.scale(0.9 + 0.2 * Math.sin(this.theta), 1)
322
- context.beginPath()
323
- context.moveTo(0, 0)
324
- context.quadraticCurveTo(5, 10, 20, 8)
325
- context.quadraticCurveTo(12, 5, 10, 0)
326
- context.quadraticCurveTo(12, -5, 20, -8)
327
- context.quadraticCurveTo(5, -10, 0, 0)
328
- context.fill()
329
- context.restore()
330
- context.save()
331
- context.translate(-3, 0)
332
- context.rotate((Math.PI / 3 + (Math.PI / 10) * Math.sin(this.phi)) * (this.renderer.reverse ? -1 : 1))
333
- context.beginPath()
334
- if (this.renderer.reverse) {
335
- context.moveTo(5, 0)
336
- context.bezierCurveTo(10, 10, 10, 30, 0, 40)
337
- context.bezierCurveTo(-12, 25, -8, 10, 0, 0)
338
- }
339
- else {
340
- context.moveTo(-5, 0)
341
- context.bezierCurveTo(-10, -10, -10, -30, 0, -40)
342
- context.bezierCurveTo(12, -25, 8, -10, 0, 0)
343
- }
344
- context.closePath()
345
- context.fill()
346
- context.restore()
347
- context.restore()
348
- this.controlStatus(context)
349
- },
350
- }
351
-
352
- export { RENDERER }
1
+ /* eslint-disable ts/no-use-before-define */
2
+ /* eslint-disable eqeqeq */
3
+
4
+ class RENDERER {
5
+ ENABLE = false
6
+ POINT_INTERVAL = 5
7
+ FISH_COUNT = 3
8
+ MAX_INTERVAL_COUNT = 50
9
+ INIT_HEIGHT_RATE = 0.5
10
+ THRESHOLD = 50
11
+
12
+ COLOR = 'hsl(0, 0%, 95%)'
13
+
14
+ constructor(color) {
15
+ if (this.ENABLE)
16
+ return
17
+
18
+ this.setColor(color)
19
+ this.removeCanvas()
20
+ this.setParameters()
21
+ this.reconstructMethods()
22
+ this.setup()
23
+ this.bindEvent()
24
+ this.render()
25
+ this.ENABLE = true
26
+ }
27
+
28
+ removeCanvas() {
29
+ const container = document.querySelector('#jsi-flying-fish-container')
30
+ const canvas = container.querySelector('canvas')
31
+ if (canvas)
32
+ canvas.remove()
33
+ }
34
+
35
+ setColor(color) {
36
+ if (color)
37
+ this.COLOR = color
38
+ }
39
+
40
+ setParameters() {
41
+ this.$window = $(window)
42
+ this.$container = $('#jsi-flying-fish-container')
43
+ this.$canvas = $('<canvas />')
44
+ this.context = this.$canvas.appendTo(this.$container).get(0).getContext('2d')
45
+ this.points = []
46
+ this.fishes = []
47
+ this.watchIds = []
48
+ }
49
+
50
+ createSurfacePoints() {
51
+ const count = Math.round(this.width / this.POINT_INTERVAL)
52
+ this.pointInterval = this.width / (count - 1)
53
+ this.points.push(new SURFACE_POINT(this, 0))
54
+ for (let i = 1; i < count; i++) {
55
+ const point = new SURFACE_POINT(this, i * this.pointInterval)
56
+ const previous = this.points[i - 1]
57
+ point.setPreviousPoint(previous)
58
+ previous.setNextPoint(point)
59
+ this.points.push(point)
60
+ }
61
+ }
62
+
63
+ reconstructMethods() {
64
+ this.watchWindowSize = this.watchWindowSize.bind(this)
65
+ this.jdugeToStopResize = this.jdugeToStopResize.bind(this)
66
+ this.startEpicenter = this.startEpicenter.bind(this)
67
+ this.moveEpicenter = this.moveEpicenter.bind(this)
68
+ this.reverseVertical = this.reverseVertical.bind(this)
69
+ this.render = this.render.bind(this)
70
+ }
71
+
72
+ setup() {
73
+ this.points.length = 0
74
+ this.fishes.length = 0
75
+ this.watchIds.length = 0
76
+ this.intervalCount = this.MAX_INTERVAL_COUNT
77
+ this.width = this.$container.width()
78
+ this.height = this.$container.height()
79
+ this.fishCount = (((this.FISH_COUNT * this.width) / 500) * this.height) / 500
80
+ this.$canvas.attr({ width: this.width, height: this.height })
81
+ this.reverse = false
82
+ this.fishes.push(new FISH(this))
83
+ this.createSurfacePoints()
84
+ }
85
+
86
+ watchWindowSize() {
87
+ this.clearTimer()
88
+ this.tmpWidth = this.$window.width()
89
+ this.tmpHeight = this.$window.height()
90
+ this.watchIds.push(setTimeout(this.jdugeToStopResize, this.WATCH_INTERVAL))
91
+ }
92
+
93
+ clearTimer() {
94
+ while (this.watchIds.length > 0)
95
+ clearTimeout(this.watchIds.pop())
96
+ }
97
+
98
+ jdugeToStopResize() {
99
+ const width = this.$window.width()
100
+ const height = this.$window.height()
101
+ const stopped = width == this.tmpWidth && height == this.tmpHeight
102
+ this.tmpWidth = width
103
+ this.tmpHeight = height
104
+ if (stopped)
105
+ this.setup()
106
+ }
107
+
108
+ bindEvent() {
109
+ this.$window.on('resize', this.watchWindowSize)
110
+ this.$container.on('mouseenter', this.startEpicenter)
111
+ this.$container.on('mousemove', this.moveEpicenter)
112
+ }
113
+
114
+ getAxis(event) {
115
+ const offset = this.$container.offset()
116
+ return { x: event.clientX - offset.left + this.$window.scrollLeft(), y: event.clientY - offset.top + this.$window.scrollTop() }
117
+ }
118
+
119
+ startEpicenter(event) {
120
+ this.axis = this.getAxis(event)
121
+ }
122
+
123
+ moveEpicenter(event) {
124
+ const axis = this.getAxis(event)
125
+ if (!this.axis)
126
+ this.axis = axis
127
+
128
+ this.generateEpicenter(axis.x, axis.y, axis.y - this.axis.y)
129
+ this.axis = axis
130
+ }
131
+
132
+ generateEpicenter(x, y, velocity) {
133
+ if (y < this.height / 2 - this.THRESHOLD || y > this.height / 2 + this.THRESHOLD)
134
+ return
135
+
136
+ const index = Math.round(x / this.pointInterval)
137
+ if (index < 0 || index >= this.points.length)
138
+ return
139
+
140
+ if (this.points[index])
141
+ this.points[index].interfere(y, velocity)
142
+ }
143
+
144
+ reverseVertical() {
145
+ this.reverse = !this.reverse
146
+ for (let i = 0, count = this.fishes.length; i < count; i++)
147
+ this.fishes[i].reverseVertical()
148
+ }
149
+
150
+ controlStatus() {
151
+ for (let i = 0, count = this.points.length; i < count; i++)
152
+ this.points[i].updateSelf()
153
+
154
+ for (let i = 0, count = this.points.length; i < count; i++)
155
+ this.points[i].updateNeighbors()
156
+
157
+ if (this.fishes.length < this.fishCount && --this.intervalCount == 0) {
158
+ this.intervalCount = this.MAX_INTERVAL_COUNT
159
+ this.fishes.push(new FISH(this))
160
+ }
161
+ }
162
+
163
+ render() {
164
+ requestAnimationFrame(this.render)
165
+ this.controlStatus()
166
+ this.context.clearRect(0, 0, this.width, this.height)
167
+ this.context.fillStyle = this.COLOR
168
+ for (let i = 0, count = this.fishes.length; i < count; i++)
169
+ this.fishes[i].render(this.context)
170
+
171
+ this.context.save()
172
+ this.context.globalCompositeOperation = 'xor'
173
+ this.context.beginPath()
174
+ this.context.moveTo(0, this.reverse ? 0 : this.height)
175
+ for (let i = 0, count = this.points.length; i < count; i++)
176
+ this.points[i].render(this.context)
177
+
178
+ this.context.lineTo(this.width, this.reverse ? 0 : this.height)
179
+ this.context.closePath()
180
+ this.context.fill()
181
+ this.context.restore()
182
+ }
183
+ }
184
+
185
+ const SURFACE_POINT = function (renderer, x) {
186
+ this.renderer = renderer
187
+ this.x = x
188
+ this.init()
189
+ }
190
+
191
+ SURFACE_POINT.prototype = {
192
+ SPRING_CONSTANT: 0.03,
193
+ SPRING_FRICTION: 0.9,
194
+ WAVE_SPREAD: 0.3,
195
+ ACCELARATION_RATE: 0.01,
196
+ init() {
197
+ this.initHeight = this.renderer.height * this.renderer.INIT_HEIGHT_RATE
198
+ this.height = this.initHeight
199
+ this.fy = 0
200
+ this.force = { previous: 0, next: 0 }
201
+ },
202
+ setPreviousPoint(previous) {
203
+ this.previous = previous
204
+ },
205
+ setNextPoint(next) {
206
+ this.next = next
207
+ },
208
+ interfere(y, velocity) {
209
+ this.fy = this.renderer.height * this.ACCELARATION_RATE * (this.renderer.height - this.height - y >= 0 ? -1 : 1) * Math.abs(velocity)
210
+ },
211
+ updateSelf() {
212
+ this.fy += this.SPRING_CONSTANT * (this.initHeight - this.height)
213
+ this.fy *= this.SPRING_FRICTION
214
+ this.height += this.fy
215
+ },
216
+ updateNeighbors() {
217
+ if (this.previous)
218
+ this.force.previous = this.WAVE_SPREAD * (this.height - this.previous.height)
219
+
220
+ if (this.next)
221
+ this.force.next = this.WAVE_SPREAD * (this.height - this.next.height)
222
+ },
223
+ render(context) {
224
+ if (this.previous) {
225
+ this.previous.height += this.force.previous
226
+ this.previous.fy += this.force.previous
227
+ }
228
+ if (this.next) {
229
+ this.next.height += this.force.next
230
+ this.next.fy += this.force.next
231
+ }
232
+ context.lineTo(this.x, this.renderer.height - this.height)
233
+ },
234
+ }
235
+
236
+ const FISH = function (renderer) {
237
+ this.renderer = renderer
238
+ this.init()
239
+ }
240
+
241
+ FISH.prototype = {
242
+ GRAVITY: 0.4,
243
+ init() {
244
+ this.direction = Math.random() < 0.5
245
+ this.x = this.direction ? this.renderer.width + this.renderer.THRESHOLD : -this.renderer.THRESHOLD
246
+ this.previousY = this.y
247
+ this.vx = this.getRandomValue(4, 7) * (this.direction ? -1 : 1)
248
+
249
+ if (this.renderer.reverse) {
250
+ this.y = this.getRandomValue((this.renderer.height * 1) / 10, (this.renderer.height * 4) / 10)
251
+ this.vy = this.getRandomValue(2, 5)
252
+ this.ay = this.getRandomValue(0.05, 0.2)
253
+ }
254
+ else {
255
+ this.y = this.getRandomValue((this.renderer.height * 6) / 10, (this.renderer.height * 9) / 10)
256
+ this.vy = this.getRandomValue(-5, -2)
257
+ this.ay = this.getRandomValue(-0.2, -0.05)
258
+ }
259
+ this.isOut = false
260
+ this.theta = 0
261
+ this.phi = 0
262
+ },
263
+ getRandomValue(min, max) {
264
+ return min + (max - min) * Math.random()
265
+ },
266
+ reverseVertical() {
267
+ this.isOut = !this.isOut
268
+ this.ay *= -1
269
+ },
270
+ controlStatus() {
271
+ this.previousY = this.y
272
+ this.x += this.vx
273
+ this.y += this.vy
274
+ this.vy += this.ay
275
+ if (this.renderer.reverse) {
276
+ if (this.y > this.renderer.height * this.renderer.INIT_HEIGHT_RATE) {
277
+ this.vy -= this.GRAVITY
278
+ this.isOut = true
279
+ }
280
+ else {
281
+ if (this.isOut)
282
+ this.ay = this.getRandomValue(0.05, 0.2)
283
+
284
+ this.isOut = false
285
+ }
286
+ }
287
+ else {
288
+ if (this.y < this.renderer.height * this.renderer.INIT_HEIGHT_RATE) {
289
+ this.vy += this.GRAVITY
290
+ this.isOut = true
291
+ }
292
+ else {
293
+ if (this.isOut)
294
+ this.ay = this.getRandomValue(-0.2, -0.05)
295
+
296
+ this.isOut = false
297
+ }
298
+ }
299
+ if (!this.isOut) {
300
+ this.theta += Math.PI / 20
301
+ this.theta %= Math.PI * 2
302
+ this.phi += Math.PI / 30
303
+ this.phi %= Math.PI * 2
304
+ }
305
+ this.renderer.generateEpicenter(this.x + (this.direction ? -1 : 1) * this.renderer.THRESHOLD, this.y, this.y - this.previousY)
306
+ if ((this.vx > 0 && this.x > this.renderer.width + this.renderer.THRESHOLD) || (this.vx < 0 && this.x < -this.renderer.THRESHOLD))
307
+ this.init()
308
+ },
309
+ render(context) {
310
+ context.save()
311
+ context.translate(this.x, this.y)
312
+ context.rotate(Math.PI + Math.atan2(this.vy, this.vx))
313
+ context.scale(1, this.direction ? 1 : -1)
314
+ context.beginPath()
315
+ context.moveTo(-30, 0)
316
+ context.bezierCurveTo(-20, 15, 15, 10, 40, 0)
317
+ context.bezierCurveTo(15, -10, -20, -15, -30, 0)
318
+ context.fill()
319
+ context.save()
320
+ context.translate(40, 0)
321
+ context.scale(0.9 + 0.2 * Math.sin(this.theta), 1)
322
+ context.beginPath()
323
+ context.moveTo(0, 0)
324
+ context.quadraticCurveTo(5, 10, 20, 8)
325
+ context.quadraticCurveTo(12, 5, 10, 0)
326
+ context.quadraticCurveTo(12, -5, 20, -8)
327
+ context.quadraticCurveTo(5, -10, 0, 0)
328
+ context.fill()
329
+ context.restore()
330
+ context.save()
331
+ context.translate(-3, 0)
332
+ context.rotate((Math.PI / 3 + (Math.PI / 10) * Math.sin(this.phi)) * (this.renderer.reverse ? -1 : 1))
333
+ context.beginPath()
334
+ if (this.renderer.reverse) {
335
+ context.moveTo(5, 0)
336
+ context.bezierCurveTo(10, 10, 10, 30, 0, 40)
337
+ context.bezierCurveTo(-12, 25, -8, 10, 0, 0)
338
+ }
339
+ else {
340
+ context.moveTo(-5, 0)
341
+ context.bezierCurveTo(-10, -10, -10, -30, 0, -40)
342
+ context.bezierCurveTo(12, -25, 8, -10, 0, 0)
343
+ }
344
+ context.closePath()
345
+ context.fill()
346
+ context.restore()
347
+ context.restore()
348
+ this.controlStatus(context)
349
+ },
350
+ }
351
+
352
+ export { RENDERER }