@andresclua/perlindom 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/LICENSE +21 -0
- package/dist/perlindom.es.js +212 -0
- package/dist/perlindom.umd.js +1 -0
- package/package.json +14 -6
- package/readme.md +121 -50
- package/dist/PerlinDOM.es.js +0 -138
- package/dist/PerlinDOM.umd.js +0 -1
- package/docs/examples.html +0 -391
- package/public/vite.svg +0 -1
- package/src/index.html +0 -819
- package/src/js/PerlinDom.js +0 -318
- package/src/js/animated-button.js +0 -40
- package/src/js/basic-examples.js +0 -43
- package/src/js/index.js +0 -13
- package/src/js/interactive-controls.js +0 -43
- package/src/js/pause-play.js +0 -33
- package/src/js/triangle-animation.js +0 -48
- package/src/scss/style.scss +0 -20
- package/vite.config.js +0 -36
package/src/index.html
DELETED
|
@@ -1,819 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>PerlinDom - by Andres Clua</title>
|
|
8
|
-
|
|
9
|
-
<link rel="stylesheet" href="https://unpkg.com/@terrahq/design-system@latest/dist/style.css" />
|
|
10
|
-
|
|
11
|
-
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
12
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
13
|
-
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
14
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
15
|
-
<link href="https://fonts.googleapis.com/css2?family=Mona+Sans:ital,wght@0,200..900;1,200..900&display=swap" rel="stylesheet" />
|
|
16
|
-
<link rel="stylesheet" href="./scss/style.scss" />
|
|
17
|
-
<style>
|
|
18
|
-
body {
|
|
19
|
-
font-family: 'Arial', sans-serif;
|
|
20
|
-
line-height: 1.6;
|
|
21
|
-
color: #333;
|
|
22
|
-
max-width: 1200px;
|
|
23
|
-
margin: 0 auto;
|
|
24
|
-
padding: 20px;
|
|
25
|
-
background-color: #f0f0f0;
|
|
26
|
-
overflow-x: hidden;
|
|
27
|
-
overflow: visible!important;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
h1, h2 {
|
|
31
|
-
color: #2c3e50;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.example-container {
|
|
35
|
-
margin-bottom: 40px;
|
|
36
|
-
border: 1px solid #ddd;
|
|
37
|
-
border-radius: 8px;
|
|
38
|
-
padding: 20px;
|
|
39
|
-
position: relative;
|
|
40
|
-
overflow: hidden;
|
|
41
|
-
height: 300px;
|
|
42
|
-
background-color: #f9f9f9;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.code-block {
|
|
46
|
-
background-color: #f5f5f5;
|
|
47
|
-
padding: 15px;
|
|
48
|
-
border-radius: 5px;
|
|
49
|
-
overflow-x: auto;
|
|
50
|
-
margin-bottom: 20px;
|
|
51
|
-
font-family: monospace;
|
|
52
|
-
font-size: 14px;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/* Example 1: Basic Animation */
|
|
56
|
-
.basic-element {
|
|
57
|
-
width: 80px;
|
|
58
|
-
height: 80px;
|
|
59
|
-
background-color: #3498db;
|
|
60
|
-
border-radius: 50%;
|
|
61
|
-
position: absolute;
|
|
62
|
-
left: calc(50% - 40px);
|
|
63
|
-
top: calc(50% - 40px);
|
|
64
|
-
filter: blur(5px);
|
|
65
|
-
transform: scale(3.5) skewX(120deg);
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/* Example 2: Horizontal Only */
|
|
70
|
-
.horizontal-element {
|
|
71
|
-
width: 60px;
|
|
72
|
-
height: 60px;
|
|
73
|
-
background-color: #e74c3c;
|
|
74
|
-
border-radius: 10px;
|
|
75
|
-
position: absolute;
|
|
76
|
-
left: calc(50% - 30px); /* 50% - half width */
|
|
77
|
-
top: calc(50% - 30px); /* 50% - half height */
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/* Example 3: Multiple Elements */
|
|
81
|
-
.particle {
|
|
82
|
-
width: 230px;
|
|
83
|
-
height: 230px;
|
|
84
|
-
background:linear-gradient(to bottom right, #8e44ad, #3498db);
|
|
85
|
-
border-radius: 50%;
|
|
86
|
-
position: absolute;
|
|
87
|
-
/* opacity: 0.2; */
|
|
88
|
-
filter: blur(10px);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/* Positioning for particles - these are initial positions, PerlinDOM will animate from here */
|
|
92
|
-
.particle:nth-child(1) {
|
|
93
|
-
left: 30%;
|
|
94
|
-
top: 30%;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.particle:nth-child(2) {
|
|
98
|
-
left: 50%;
|
|
99
|
-
top: 50%;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
.particle:nth-child(3) {
|
|
103
|
-
left: 70%;
|
|
104
|
-
top: 70%;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
.particle:nth-child(4) {
|
|
108
|
-
left: 30%;
|
|
109
|
-
top: 70%;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.particle:nth-child(5) {
|
|
113
|
-
left: 70%;
|
|
114
|
-
top: 30%;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/* Example 4: Background Effect */
|
|
118
|
-
.bg-container {
|
|
119
|
-
background-color: #34495e;
|
|
120
|
-
position: relative;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.bg-element {
|
|
124
|
-
position: absolute;
|
|
125
|
-
border-radius: 50%;
|
|
126
|
-
background-color: rgba(255, 255, 255, 0.1);
|
|
127
|
-
filter: blur(5px);
|
|
128
|
-
transform: scale(3.2);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.bg-element-1 {
|
|
132
|
-
width: 100px;
|
|
133
|
-
height: 100px;
|
|
134
|
-
left: 20%;
|
|
135
|
-
top: 30%;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
.bg-element-2 {
|
|
139
|
-
width: 150px;
|
|
140
|
-
height: 150px;
|
|
141
|
-
left: 60%;
|
|
142
|
-
top: 50%;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
.bg-element-3 {
|
|
146
|
-
width: 80px;
|
|
147
|
-
height: 80px;
|
|
148
|
-
left: 40%;
|
|
149
|
-
top: 70%;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
.content {
|
|
153
|
-
position: relative;
|
|
154
|
-
z-index: 10;
|
|
155
|
-
color: white;
|
|
156
|
-
text-align: center;
|
|
157
|
-
padding-top: 120px;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/* Example 5: Pause Play Element */
|
|
161
|
-
.pause-play-container {
|
|
162
|
-
position: relative;
|
|
163
|
-
cursor: pointer;
|
|
164
|
-
height: 200px;
|
|
165
|
-
border: 1px dashed #ccc;
|
|
166
|
-
border-radius: 8px;
|
|
167
|
-
margin-top: 20px;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
.pause-play-element {
|
|
171
|
-
width: 70px;
|
|
172
|
-
height: 70px;
|
|
173
|
-
background-color: #f39c12;
|
|
174
|
-
border-radius: 50%;
|
|
175
|
-
position: absolute;
|
|
176
|
-
left: calc(50% - 35px);
|
|
177
|
-
top: calc(50% - 35px);
|
|
178
|
-
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
.status-display {
|
|
182
|
-
position: absolute;
|
|
183
|
-
bottom: 20px;
|
|
184
|
-
left: 0;
|
|
185
|
-
width: 100%;
|
|
186
|
-
text-align: center;
|
|
187
|
-
font-weight: bold;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
.status-indicator {
|
|
191
|
-
color: #2980b9;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
.instruction {
|
|
195
|
-
font-size: 14px;
|
|
196
|
-
color: #7f8c8d;
|
|
197
|
-
margin-top: 5px;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
.pause-play-settings {
|
|
201
|
-
margin-bottom: 20px;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
.setting-description {
|
|
205
|
-
font-size: 12px;
|
|
206
|
-
color: #7f8c8d;
|
|
207
|
-
margin-top: 5px;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
.lerp-value {
|
|
211
|
-
font-weight: bold;
|
|
212
|
-
color: #e67e22;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/* Example 6: Interactive Element */
|
|
216
|
-
.interactive-container {
|
|
217
|
-
display: flex;
|
|
218
|
-
justify-content: space-between;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
.controls {
|
|
222
|
-
width: 40%;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
.preview {
|
|
226
|
-
width: 55%;
|
|
227
|
-
height: 200px;
|
|
228
|
-
border: 1px solid #ddd;
|
|
229
|
-
border-radius: 5px;
|
|
230
|
-
position: relative;
|
|
231
|
-
overflow: hidden;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
.interactive-element {
|
|
235
|
-
width: 50px;
|
|
236
|
-
height: 50px;
|
|
237
|
-
background-color: #9b59b6;
|
|
238
|
-
border-radius: 50%;
|
|
239
|
-
position: absolute;
|
|
240
|
-
left: calc(50% - 25px); /* 50% - half width */
|
|
241
|
-
top: calc(50% - 25px); /* 50% - half height */
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
.control-group {
|
|
245
|
-
margin-bottom: 15px;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
label {
|
|
249
|
-
display: block;
|
|
250
|
-
margin-bottom: 5px;
|
|
251
|
-
font-weight: bold;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
input[type="range"] {
|
|
255
|
-
width: 100%;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
.value-display {
|
|
259
|
-
font-size: 12px;
|
|
260
|
-
color: #666;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
.container {
|
|
264
|
-
display: flex;
|
|
265
|
-
flex-direction: column;
|
|
266
|
-
align-items: center;
|
|
267
|
-
justify-content: center;
|
|
268
|
-
text-align: center;
|
|
269
|
-
margin-bottom: 40px;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
.instructions {
|
|
273
|
-
position: fixed;
|
|
274
|
-
bottom: 20px;
|
|
275
|
-
left: 0;
|
|
276
|
-
right: 0;
|
|
277
|
-
text-align: center;
|
|
278
|
-
color: white;
|
|
279
|
-
font-size: 1.2rem;
|
|
280
|
-
z-index: 10;
|
|
281
|
-
text-shadow: 0 0 5px rgba(0,0,0,0.5);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/* Example 7: Animated Button with Circles */
|
|
285
|
-
.animated-button-container {
|
|
286
|
-
display: flex;
|
|
287
|
-
justify-content: center;
|
|
288
|
-
align-items: center;
|
|
289
|
-
height: 100%;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
.animated-button {
|
|
293
|
-
position: relative;
|
|
294
|
-
display: inline-block;
|
|
295
|
-
padding: 15px 30px;
|
|
296
|
-
background-color: #3498db;
|
|
297
|
-
color: white;
|
|
298
|
-
text-decoration: none;
|
|
299
|
-
font-weight: bold;
|
|
300
|
-
border-radius: 5px;
|
|
301
|
-
overflow: visible;
|
|
302
|
-
transition: background-color 0.3s;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
.animated-button:hover {
|
|
306
|
-
background-color: #2980b9;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
.animated-button .circle {
|
|
310
|
-
position: absolute;
|
|
311
|
-
width: 60px;
|
|
312
|
-
height: 60px;
|
|
313
|
-
background-color:#3498db;
|
|
314
|
-
border-radius: 50%;
|
|
315
|
-
opacity: 0;
|
|
316
|
-
transition: opacity 0.3s;
|
|
317
|
-
pointer-events: none;
|
|
318
|
-
filter: blur(19px);
|
|
319
|
-
z-index: 1;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
.animated-button:hover .circle {
|
|
323
|
-
opacity: 1;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
.animated-button .circle:nth-child(1) {
|
|
327
|
-
left: -15px;
|
|
328
|
-
top: 50%;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
.animated-button .circle:nth-child(2) {
|
|
332
|
-
left: 50%;
|
|
333
|
-
top: -15px;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.animated-button .circle:nth-child(3) {
|
|
337
|
-
right: -15px;
|
|
338
|
-
top: 50%;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
.animated-button .circle:nth-child(4) {
|
|
342
|
-
left: 50%;
|
|
343
|
-
bottom: -15px;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
.animated-button .button-text {
|
|
347
|
-
position: relative;
|
|
348
|
-
z-index: 10;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/* Example 8: ClipPath Triangle with Animated Vertex */
|
|
352
|
-
.triangle-container {
|
|
353
|
-
display: flex;
|
|
354
|
-
justify-content: center;
|
|
355
|
-
align-items: center;
|
|
356
|
-
height: 100%;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
.triangle-svg {
|
|
360
|
-
width: 300px;
|
|
361
|
-
height: 300px;
|
|
362
|
-
overflow: visible;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
.triangle-content {
|
|
366
|
-
width: 100%;
|
|
367
|
-
height: 100%;
|
|
368
|
-
background: linear-gradient(135deg, #3498db, #e74c3c, #9b59b6);
|
|
369
|
-
animation: gradientShift 10s ease infinite;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
@keyframes gradientShift {
|
|
373
|
-
0% { background-position: 0% 50%; }
|
|
374
|
-
50% { background-position: 100% 50%; }
|
|
375
|
-
100% { background-position: 0% 50%; }
|
|
376
|
-
}
|
|
377
|
-
</style>
|
|
378
|
-
</head>
|
|
379
|
-
|
|
380
|
-
<body>
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
<div class="container">
|
|
384
|
-
<h1>PerlinSVG Example</h1>
|
|
385
|
-
</div>
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
<h1>PerlinDOM Examples</h1>
|
|
389
|
-
<p>This page demonstrates various ways to use the PerlinDOM library for creating smooth, organic animations.</p>
|
|
390
|
-
|
|
391
|
-
<!-- Example 1: Basic Animation -->
|
|
392
|
-
<h2>1. Basic Animation</h2>
|
|
393
|
-
<div class="code-block">
|
|
394
|
-
const basicAnimation = new PerlinDOM({<br>
|
|
395
|
-
element: document.querySelector('.basic-element'),<br>
|
|
396
|
-
x: { min: -50, max: 50 },<br>
|
|
397
|
-
y: { min: -50, max: 50 },<br>
|
|
398
|
-
speed: 0.01,<br>
|
|
399
|
-
seed: 123<br>
|
|
400
|
-
});
|
|
401
|
-
</div>
|
|
402
|
-
<div class="example-container">
|
|
403
|
-
<div class="basic-element"></div>
|
|
404
|
-
</div>
|
|
405
|
-
|
|
406
|
-
<!-- Example 2: Horizontal Only -->
|
|
407
|
-
<h2>2. Horizontal-Only Movement</h2>
|
|
408
|
-
<div class="code-block">
|
|
409
|
-
const horizontalAnimation = new PerlinDOM({<br>
|
|
410
|
-
element: document.querySelector('.horizontal-element'),<br>
|
|
411
|
-
x: { min: -100, max: 100 },<br>
|
|
412
|
-
y: null, // No vertical movement<br>
|
|
413
|
-
speed: 0.02<br>
|
|
414
|
-
});
|
|
415
|
-
</div>
|
|
416
|
-
<div class="example-container">
|
|
417
|
-
<div class="horizontal-element"></div>
|
|
418
|
-
</div>
|
|
419
|
-
|
|
420
|
-
<!-- Example 3: Multiple Elements -->
|
|
421
|
-
<h2>3. Multiple Elements with Different Seeds</h2>
|
|
422
|
-
<div class="code-block">
|
|
423
|
-
document.querySelectorAll('.particle').forEach((el, index) => {<br>
|
|
424
|
-
new PerlinDOM({<br>
|
|
425
|
-
element: el,<br>
|
|
426
|
-
x: { min: -100, max: 100 },<br>
|
|
427
|
-
y: { min: -100, max: 100 },<br>
|
|
428
|
-
speed: 0.01,<br>
|
|
429
|
-
seed: index * 100 // Different seed for each element<br>
|
|
430
|
-
});<br>
|
|
431
|
-
});
|
|
432
|
-
</div>
|
|
433
|
-
<div class="example-container">
|
|
434
|
-
<div class="particle"></div>
|
|
435
|
-
<div class="particle"></div>
|
|
436
|
-
<div class="particle"></div>
|
|
437
|
-
<div class="particle"></div>
|
|
438
|
-
<div class="particle"></div>
|
|
439
|
-
</div>
|
|
440
|
-
|
|
441
|
-
<!-- Example 4: Background Effect -->
|
|
442
|
-
<h2>4. Creating a Background Effect</h2>
|
|
443
|
-
<div class="code-block">
|
|
444
|
-
document.querySelectorAll('.bg-element').forEach(el => {<br>
|
|
445
|
-
new PerlinDOM({<br>
|
|
446
|
-
element: el,<br>
|
|
447
|
-
x: { min: -10, max: 10 },<br>
|
|
448
|
-
y: { min: -10, max: 10 },<br>
|
|
449
|
-
speed: 0.002, // Very slow movement<br>
|
|
450
|
-
seed: Math.random() * 2000<br>
|
|
451
|
-
});<br>
|
|
452
|
-
});
|
|
453
|
-
</div>
|
|
454
|
-
<div class="example-container bg-container">
|
|
455
|
-
<div class="bg-element bg-element-1"></div>
|
|
456
|
-
<div class="bg-element bg-element-2"></div>
|
|
457
|
-
<div class="bg-element bg-element-3"></div>
|
|
458
|
-
<div class="content">
|
|
459
|
-
<h3>Subtle Background Animation</h3>
|
|
460
|
-
<p>Perfect for creating depth in UI elements</p>
|
|
461
|
-
</div>
|
|
462
|
-
</div>
|
|
463
|
-
|
|
464
|
-
<!-- Example 5: Pause and Play with Mouse Events -->
|
|
465
|
-
<h2>5. Smooth Pause and Play with Mouse Events</h2>
|
|
466
|
-
<div class="code-block">
|
|
467
|
-
const pausePlayAnimation = new PerlinDOM({<br>
|
|
468
|
-
element: document.querySelector('.pause-play-element'),<br>
|
|
469
|
-
x: { min: -80, max: 80 },<br>
|
|
470
|
-
y: { min: -80, max: 80 },<br>
|
|
471
|
-
speed: 0.01,<br>
|
|
472
|
-
seed: 42,<br>
|
|
473
|
-
lerpSpeed: 0.05 // Controls how smooth the transition is<br>
|
|
474
|
-
});<br><br>
|
|
475
|
-
|
|
476
|
-
// Pause on mouse leave<br>
|
|
477
|
-
document.querySelector('.pause-play-container').addEventListener('mouseleave', () => {<br>
|
|
478
|
-
pausePlayAnimation.pause();<br>
|
|
479
|
-
document.querySelector('.status-indicator').textContent = 'Pausing...';<br>
|
|
480
|
-
});<br><br>
|
|
481
|
-
|
|
482
|
-
// Play on mouse enter<br>
|
|
483
|
-
document.querySelector('.pause-play-container').addEventListener('mouseenter', () => {<br>
|
|
484
|
-
pausePlayAnimation.play();<br>
|
|
485
|
-
document.querySelector('.status-indicator').textContent = 'Playing...';<br>
|
|
486
|
-
});<br><br>
|
|
487
|
-
|
|
488
|
-
// Update lerpSpeed when slider changes<br>
|
|
489
|
-
document.getElementById('lerp-speed').addEventListener('input', (e) => {<br>
|
|
490
|
-
const newSpeed = parseFloat(e.target.value);<br>
|
|
491
|
-
pausePlayAnimation.lerpSpeed = newSpeed;<br>
|
|
492
|
-
document.querySelector('.lerp-value').textContent = newSpeed.toFixed(2);<br>
|
|
493
|
-
});
|
|
494
|
-
</div>
|
|
495
|
-
<div class="example-container">
|
|
496
|
-
<div class="pause-play-settings">
|
|
497
|
-
<label for="lerp-speed">Transition Speed: <span class="lerp-value">0.05</span></label>
|
|
498
|
-
<input type="range" id="lerp-speed" min="0.01" max="0.2" step="0.01" value="0.05">
|
|
499
|
-
<p class="setting-description">Lower values = smoother, slower transitions</p>
|
|
500
|
-
</div>
|
|
501
|
-
<div class="pause-play-container">
|
|
502
|
-
<div class="pause-play-element"></div>
|
|
503
|
-
<div class="status-display">
|
|
504
|
-
Status: <span class="status-indicator">Playing</span>
|
|
505
|
-
<p class="instruction">Hover over this orange circle to play, move mouse out to pause</p>
|
|
506
|
-
</div>
|
|
507
|
-
</div>
|
|
508
|
-
</div>
|
|
509
|
-
|
|
510
|
-
<!-- Example 6: Interactive Controls -->
|
|
511
|
-
<h2>6. Interactive Controls</h2>
|
|
512
|
-
<div class="code-block">
|
|
513
|
-
// Create the animation with initial settings<br>
|
|
514
|
-
const interactiveAnimation = new PerlinDOM({<br>
|
|
515
|
-
element: document.querySelector('.interactive-element'),<br>
|
|
516
|
-
x: { min: -50, max: 50 },<br>
|
|
517
|
-
y: { min: -50, max: 50 },<br>
|
|
518
|
-
speed: 0.01,<br>
|
|
519
|
-
seed: 0<br>
|
|
520
|
-
});<br><br>
|
|
521
|
-
|
|
522
|
-
// Update settings based on user input<br>
|
|
523
|
-
speedControl.addEventListener('input', () => {<br>
|
|
524
|
-
// Stop current animation<br>
|
|
525
|
-
interactiveAnimation.destroy();<br>
|
|
526
|
-
<br>
|
|
527
|
-
// Reinitialize with new settings<br>
|
|
528
|
-
interactiveAnimation.speed = parseFloat(speedControl.value);<br>
|
|
529
|
-
interactiveAnimation.init(seedControl.value);<br>
|
|
530
|
-
});
|
|
531
|
-
</div>
|
|
532
|
-
<div class="example-container">
|
|
533
|
-
<div class="interactive-container">
|
|
534
|
-
<div class="controls">
|
|
535
|
-
<div class="control-group">
|
|
536
|
-
<label for="x-range">X Range:</label>
|
|
537
|
-
<input type="range" id="x-range" min="0" max="100" value="50">
|
|
538
|
-
<div class="value-display">-50 to 50</div>
|
|
539
|
-
</div>
|
|
540
|
-
|
|
541
|
-
<div class="control-group">
|
|
542
|
-
<label for="y-range">Y Range:</label>
|
|
543
|
-
<input type="range" id="y-range" min="0" max="100" value="50">
|
|
544
|
-
<div class="value-display">-50 to 50</div>
|
|
545
|
-
</div>
|
|
546
|
-
|
|
547
|
-
<div class="control-group">
|
|
548
|
-
<label for="speed">Speed:</label>
|
|
549
|
-
<input type="range" id="speed" min="0.001" max="0.05" step="0.001" value="0.01">
|
|
550
|
-
<div class="value-display">0.01</div>
|
|
551
|
-
</div>
|
|
552
|
-
|
|
553
|
-
<div class="control-group">
|
|
554
|
-
<label for="seed">Seed:</label>
|
|
555
|
-
<input type="range" id="seed" min="0" max="1000" step="1" value="0">
|
|
556
|
-
<div class="value-display">0</div>
|
|
557
|
-
</div>
|
|
558
|
-
</div>
|
|
559
|
-
|
|
560
|
-
<div class="preview">
|
|
561
|
-
<div class="interactive-element"></div>
|
|
562
|
-
</div>
|
|
563
|
-
</div>
|
|
564
|
-
</div>
|
|
565
|
-
|
|
566
|
-
<!-- Example 7: Animated Button with Circles -->
|
|
567
|
-
<h2>7. Animated Button with Circles on Hover</h2>
|
|
568
|
-
<div class="code-block">
|
|
569
|
-
// Get all the circle elements inside the button<br>
|
|
570
|
-
const circleElements = document.querySelectorAll('.animated-button .circle');<br><br>
|
|
571
|
-
|
|
572
|
-
// Create an array to store the animation instances<br>
|
|
573
|
-
let circleAnimations = [];<br><br>
|
|
574
|
-
|
|
575
|
-
// Function to initialize animations<br>
|
|
576
|
-
function initCircleAnimations() {<br>
|
|
577
|
-
// Clear any existing animations<br>
|
|
578
|
-
circleAnimations.forEach(anim => anim.destroy());<br>
|
|
579
|
-
circleAnimations = [];<br><br>
|
|
580
|
-
|
|
581
|
-
// Create new animations for each circle<br>
|
|
582
|
-
circleElements.forEach((el, index) => {<br>
|
|
583
|
-
const animation = new PerlinDOM({<br>
|
|
584
|
-
element: el,<br>
|
|
585
|
-
x: { min: -15, max: 15 },<br>
|
|
586
|
-
y: { min: -15, max: 15 },<br>
|
|
587
|
-
speed: 0.03,<br>
|
|
588
|
-
seed: index * 1000,<br>
|
|
589
|
-
lerpSpeed: 0.1<br>
|
|
590
|
-
});<br>
|
|
591
|
-
circleAnimations.push(animation);<br>
|
|
592
|
-
});<br>
|
|
593
|
-
}<br><br>
|
|
594
|
-
|
|
595
|
-
// Add event listeners to the button<br>
|
|
596
|
-
document.querySelector('.animated-button').addEventListener('mouseenter', () => {<br>
|
|
597
|
-
initCircleAnimations();<br>
|
|
598
|
-
circleAnimations.forEach(anim => anim.play());<br>
|
|
599
|
-
});<br><br>
|
|
600
|
-
|
|
601
|
-
document.querySelector('.animated-button').addEventListener('mouseleave', () => {<br>
|
|
602
|
-
circleAnimations.forEach(anim => anim.pause());<br>
|
|
603
|
-
});
|
|
604
|
-
</div>
|
|
605
|
-
<div class="example-container">
|
|
606
|
-
<div class="animated-button-container">
|
|
607
|
-
<a href="#" class="animated-button">
|
|
608
|
-
<span class="circle"></span>
|
|
609
|
-
<span class="circle"></span>
|
|
610
|
-
<span class="circle"></span>
|
|
611
|
-
<span class="circle"></span>
|
|
612
|
-
<span class="button-text">Button Text</span>
|
|
613
|
-
</a>
|
|
614
|
-
</div>
|
|
615
|
-
</div>
|
|
616
|
-
|
|
617
|
-
<!-- Example 8: ClipPath Triangle with Animated Vertex -->
|
|
618
|
-
<h2>8. ClipPath Triangle with Animated Vertex</h2>
|
|
619
|
-
<div class="code-block">
|
|
620
|
-
// Get the polygon element<br>
|
|
621
|
-
const trianglePath = document.getElementById('trianglePath');<br><br>
|
|
622
|
-
|
|
623
|
-
// Store the original points<br>
|
|
624
|
-
const originalPoints = {<br>
|
|
625
|
-
x1: 150, y1: 50, // Top vertex<br>
|
|
626
|
-
x2: 250, y2: 250, // Bottom right<br>
|
|
627
|
-
x3: 50, y3: 250 // Bottom left<br>
|
|
628
|
-
};<br><br>
|
|
629
|
-
|
|
630
|
-
// Create a custom animation function<br>
|
|
631
|
-
function animateTriangle() {<br>
|
|
632
|
-
// Create a PerlinDOM instance for the top vertex<br>
|
|
633
|
-
const topVertexAnimation = new PerlinDOM({<br>
|
|
634
|
-
element: null, // We're not moving a DOM element directly<br>
|
|
635
|
-
x: { min: -30, max: 30 },<br>
|
|
636
|
-
y: { min: -20, max: 20 },<br>
|
|
637
|
-
speed: 0.005,<br>
|
|
638
|
-
seed: 42<br>
|
|
639
|
-
});<br><br>
|
|
640
|
-
|
|
641
|
-
// Animation function<br>
|
|
642
|
-
function updateTriangle() {<br>
|
|
643
|
-
// Get the current noise values<br>
|
|
644
|
-
const offsetX = topVertexAnimation.lastX;<br>
|
|
645
|
-
const offsetY = topVertexAnimation.lastY;<br><br>
|
|
646
|
-
|
|
647
|
-
// Update the polygon points<br>
|
|
648
|
-
const newPoints = `${originalPoints.x1 + offsetX},${originalPoints.y1 + offsetY} ${originalPoints.x2},${originalPoints.y2} ${originalPoints.x3},${originalPoints.y3}`;<br>
|
|
649
|
-
trianglePath.setAttribute('points', newPoints);<br><br>
|
|
650
|
-
|
|
651
|
-
// Continue animation<br>
|
|
652
|
-
requestAnimationFrame(updateTriangle);<br>
|
|
653
|
-
}<br><br>
|
|
654
|
-
|
|
655
|
-
// Start the animation<br>
|
|
656
|
-
updateTriangle();<br>
|
|
657
|
-
}<br><br>
|
|
658
|
-
|
|
659
|
-
// Initialize the animation<br>
|
|
660
|
-
animateTriangle();
|
|
661
|
-
</div>
|
|
662
|
-
<div class="example-container">
|
|
663
|
-
<div class="triangle-container">
|
|
664
|
-
<svg class="triangle-svg" viewBox="0 0 300 300">
|
|
665
|
-
<defs>
|
|
666
|
-
<clipPath id="triangleClip">
|
|
667
|
-
<polygon id="trianglePath" points="150,50 250,250 50,250"></polygon>
|
|
668
|
-
</clipPath>
|
|
669
|
-
</defs>
|
|
670
|
-
<rect class="triangle-content" width="300" height="300" clip-path="url(#triangleClip)"></rect>
|
|
671
|
-
</svg>
|
|
672
|
-
</div>
|
|
673
|
-
</div>
|
|
674
|
-
|
|
675
|
-
<!-- Example 9: Pixel vs. Percentage Values -->
|
|
676
|
-
<h2>9. Pixel vs. Percentage Values</h2>
|
|
677
|
-
<div class="code-block">
|
|
678
|
-
// Pixel-based animation (fixed size)<br>
|
|
679
|
-
const pixelAnimation = new PerlinDOM({<br>
|
|
680
|
-
element: document.querySelector('.pixel-element'),<br>
|
|
681
|
-
x: { min: -50, max: 50 },<br>
|
|
682
|
-
y: { min: -50, max: 50 },<br>
|
|
683
|
-
speed: 0.01,<br>
|
|
684
|
-
seed: 123<br>
|
|
685
|
-
});<br><br>
|
|
686
|
-
|
|
687
|
-
// Percentage-based animation (responsive)<br>
|
|
688
|
-
const percentageAnimation = new PerlinDOM({<br>
|
|
689
|
-
element: document.querySelector('.percentage-element'),<br>
|
|
690
|
-
x: { min: '-20%', max: '20%' },<br>
|
|
691
|
-
y: { min: '-20%', max: '20%' },<br>
|
|
692
|
-
speed: 0.01,<br>
|
|
693
|
-
seed: 123<br>
|
|
694
|
-
});
|
|
695
|
-
</div>
|
|
696
|
-
<div class="example-container">
|
|
697
|
-
<div style="display: flex; justify-content: space-between; height: 100%;">
|
|
698
|
-
<div style="width: 48%; height: 100%; position: relative; border: 1px dashed #ccc; border-radius: 5px; overflow: hidden;">
|
|
699
|
-
<div style="position: absolute; top: 10px; left: 0; width: 100%; text-align: center; font-weight: bold; color: #7f8c8d; z-index: 10;">Pixel Values (Fixed)</div>
|
|
700
|
-
<div class="pixel-element" style="width: 80px; height: 80px; background-color: #3498db; border-radius: 50%; position: absolute; left: calc(50% - 40px); top: calc(50% - 40px); filter: blur(5px);"></div>
|
|
701
|
-
<div style="position: absolute; bottom: 10px; left: 0; width: 100%; text-align: center; font-size: 12px; color: #7f8c8d;">Resize your browser window - animation range stays the same</div>
|
|
702
|
-
</div>
|
|
703
|
-
<div style="width: 48%; height: 100%; position: relative; border: 1px dashed #ccc; border-radius: 5px; overflow: hidden;">
|
|
704
|
-
<div style="position: absolute; top: 10px; left: 0; width: 100%; text-align: center; font-weight: bold; color: #7f8c8d; z-index: 10;">Percentage Values (Responsive)</div>
|
|
705
|
-
<div class="percentage-element" style="width: 80px; height: 80px; background-color: #e74c3c; border-radius: 50%; position: absolute; left: calc(50% - 40px); top: calc(50% - 40px); filter: blur(5px);"></div>
|
|
706
|
-
<div style="position: absolute; bottom: 10px; left: 0; width: 100%; text-align: center; font-size: 12px; color: #7f8c8d;">Resize your browser window - animation range adapts</div>
|
|
707
|
-
</div>
|
|
708
|
-
</div>
|
|
709
|
-
</div>
|
|
710
|
-
|
|
711
|
-
<!-- Example 10: Resizable Container with Percentage Values -->
|
|
712
|
-
<h2>10. Resizable Container with Percentage Values</h2>
|
|
713
|
-
<div class="code-block">
|
|
714
|
-
const responsiveAnimation = new PerlinDOM({<br>
|
|
715
|
-
element: document.querySelector('.responsive-element'),<br>
|
|
716
|
-
x: { min: '-25%', max: '25%' },<br>
|
|
717
|
-
y: { min: '-25%', max: '25%' },<br>
|
|
718
|
-
speed: 0.008,<br>
|
|
719
|
-
seed: 456<br>
|
|
720
|
-
});
|
|
721
|
-
</div>
|
|
722
|
-
<div class="example-container">
|
|
723
|
-
<div style="height: 100%; position: relative; border: 1px solid #ddd; border-radius: 5px; overflow: hidden; resize: both; min-width: 200px; min-height: 200px; background-color: #f0f0f0;">
|
|
724
|
-
<div class="responsive-element" style="width: 60px; height: 60px; background-color: #9b59b6; border-radius: 50%; position: absolute; left: calc(50% - 30px); top: calc(50% - 30px);"></div>
|
|
725
|
-
<div style="position: absolute; bottom: 10px; right: 10px; font-size: 12px; color: #7f8c8d;">↘️ Drag this corner to resize the container</div>
|
|
726
|
-
</div>
|
|
727
|
-
</div>
|
|
728
|
-
|
|
729
|
-
<!-- Example 11: Mixed Pixel and Percentage Values -->
|
|
730
|
-
<h2>11. Mixed Pixel and Percentage Values</h2>
|
|
731
|
-
<div class="code-block">
|
|
732
|
-
// Horizontal percentage, vertical pixel<br>
|
|
733
|
-
const horizontalPercentAnimation = new PerlinDOM({<br>
|
|
734
|
-
element: document.querySelector('.horizontal-percent-element'),<br>
|
|
735
|
-
x: { min: '-30%', max: '30%' },<br>
|
|
736
|
-
y: { min: -40, max: 40 },<br>
|
|
737
|
-
speed: 0.01,<br>
|
|
738
|
-
seed: 789<br>
|
|
739
|
-
});<br><br>
|
|
740
|
-
|
|
741
|
-
// Horizontal pixel, vertical percentage<br>
|
|
742
|
-
const verticalPercentAnimation = new PerlinDOM({<br>
|
|
743
|
-
element: document.querySelector('.vertical-percent-element'),<br>
|
|
744
|
-
x: { min: -80, max: 80 },<br>
|
|
745
|
-
y: { min: '-20%', max: '20%' },<br>
|
|
746
|
-
speed: 0.01,<br>
|
|
747
|
-
seed: 789<br>
|
|
748
|
-
});
|
|
749
|
-
</div>
|
|
750
|
-
<div class="example-container">
|
|
751
|
-
<div style="display: flex; justify-content: space-between; height: 100%;">
|
|
752
|
-
<div style="width: 48%; height: 100%; position: relative; border: 1px dashed #ccc; border-radius: 5px; overflow: hidden;">
|
|
753
|
-
<div style="position: absolute; top: 10px; left: 0; width: 100%; text-align: center; font-weight: bold; color: #7f8c8d; z-index: 10;">Horizontal % / Vertical px</div>
|
|
754
|
-
<div class="horizontal-percent-element" style="width: 60px; height: 60px; background-color: #f39c12; border-radius: 10px; position: absolute; left: calc(50% - 30px); top: calc(50% - 30px);"></div>
|
|
755
|
-
<div style="position: absolute; bottom: 10px; left: 0; width: 100%; text-align: center; font-size: 12px; color: #7f8c8d;">Horizontal movement adapts to width, vertical is fixed</div>
|
|
756
|
-
</div>
|
|
757
|
-
<div style="width: 48%; height: 100%; position: relative; border: 1px dashed #ccc; border-radius: 5px; overflow: hidden;">
|
|
758
|
-
<div style="position: absolute; top: 10px; left: 0; width: 100%; text-align: center; font-weight: bold; color: #7f8c8d; z-index: 10;">Horizontal px / Vertical %</div>
|
|
759
|
-
<div class="vertical-percent-element" style="width: 60px; height: 60px; background-color: #f39c12; border-radius: 10px; position: absolute; left: calc(50% - 30px); top: calc(50% - 30px);"></div>
|
|
760
|
-
<div style="position: absolute; bottom: 10px; left: 0; width: 100%; text-align: center; font-size: 12px; color: #7f8c8d;">Horizontal movement is fixed, vertical adapts to height</div>
|
|
761
|
-
</div>
|
|
762
|
-
</div>
|
|
763
|
-
</div>
|
|
764
|
-
|
|
765
|
-
<!-- Load all scripts -->
|
|
766
|
-
<script type="module" src="./js/index.js"></script>
|
|
767
|
-
<script type="module" src="./js/basic-examples.js"></script>
|
|
768
|
-
<script type="module" src="./js/pause-play.js"></script>
|
|
769
|
-
<script type="module" src="./js/interactive-controls.js"></script>
|
|
770
|
-
<script type="module" src="./js/animated-button.js"></script>
|
|
771
|
-
<script type="module" src="./js/triangle-animation.js"></script>
|
|
772
|
-
<script type="module">
|
|
773
|
-
import PerlinDOM from './js/PerlinDom.js';
|
|
774
|
-
|
|
775
|
-
// Example 9: Pixel vs. Percentage Values
|
|
776
|
-
const pixelAnimation = new PerlinDOM({
|
|
777
|
-
element: document.querySelector('.pixel-element'),
|
|
778
|
-
x: { min: -50, max: 50 },
|
|
779
|
-
y: { min: -50, max: 50 },
|
|
780
|
-
speed: 0.01,
|
|
781
|
-
seed: 123
|
|
782
|
-
});
|
|
783
|
-
|
|
784
|
-
const percentageAnimation = new PerlinDOM({
|
|
785
|
-
element: document.querySelector('.percentage-element'),
|
|
786
|
-
x: { min: '-20%', max: '20%' },
|
|
787
|
-
y: { min: '-20%', max: '20%' },
|
|
788
|
-
speed: 0.01,
|
|
789
|
-
seed: 123
|
|
790
|
-
});
|
|
791
|
-
|
|
792
|
-
// Example 10: Resizable Container
|
|
793
|
-
const responsiveAnimation = new PerlinDOM({
|
|
794
|
-
element: document.querySelector('.responsive-element'),
|
|
795
|
-
x: { min: '-25%', max: '25%' },
|
|
796
|
-
y: { min: '-25%', max: '25%' },
|
|
797
|
-
speed: 0.008,
|
|
798
|
-
seed: 456
|
|
799
|
-
});
|
|
800
|
-
|
|
801
|
-
// Example 11: Mixed Values
|
|
802
|
-
const horizontalPercentAnimation = new PerlinDOM({
|
|
803
|
-
element: document.querySelector('.horizontal-percent-element'),
|
|
804
|
-
x: { min: '-30%', max: '30%' },
|
|
805
|
-
y: { min: -40, max: 40 },
|
|
806
|
-
speed: 0.01,
|
|
807
|
-
seed: 789
|
|
808
|
-
});
|
|
809
|
-
|
|
810
|
-
const verticalPercentAnimation = new PerlinDOM({
|
|
811
|
-
element: document.querySelector('.vertical-percent-element'),
|
|
812
|
-
x: { min: -80, max: 80 },
|
|
813
|
-
y: { min: '-20%', max: '20%' },
|
|
814
|
-
speed: 0.01,
|
|
815
|
-
seed: 789
|
|
816
|
-
});
|
|
817
|
-
</script>
|
|
818
|
-
</body>
|
|
819
|
-
</html>
|