stylpp 1.0.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/README.md +475 -0
- package/bin/stylpp.js +2 -0
- package/dist/stylpp.esm.js +726 -0
- package/dist/stylpp.esm.js.map +1 -0
- package/dist/stylpp.js +734 -0
- package/dist/stylpp.js.map +1 -0
- package/dist/stylpp.min.js +2 -0
- package/dist/stylpp.min.js.map +1 -0
- package/package.json +59 -0
- package/src/cli/index.js +400 -0
- package/src/compiler/animation.js +346 -0
- package/src/compiler/effects.js +344 -0
- package/src/compiler/generator.js +157 -0
- package/src/compiler/index.js +119 -0
- package/src/compiler/parser.js +210 -0
- package/src/compiler/physics.js +286 -0
- package/src/compiler/transformer.js +228 -0
- package/src/runtime/advanced.js +293 -0
- package/src/runtime/browser.js +239 -0
- package/stylpp-1.0.0.tgz +0 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* STYL++ Animation Engine
|
|
3
|
+
* Advanced animation system with easing, timelines, keyframes, and physics
|
|
4
|
+
* Far exceeds CSS animation capabilities
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class EasingFunctions {
|
|
8
|
+
static linear(t) {
|
|
9
|
+
return t;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static easeInQuad(t) {
|
|
13
|
+
return t * t;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static easeOutQuad(t) {
|
|
17
|
+
return t * (2 - t);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static easeInOutQuad(t) {
|
|
21
|
+
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static easeInCubic(t) {
|
|
25
|
+
return t * t * t;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static easeOutCubic(t) {
|
|
29
|
+
return 1 + --t * t * t;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static easeInOutCubic(t) {
|
|
33
|
+
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * (t - 2)) * (2 * (t - 2)) + 1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static easeInElastic(t) {
|
|
37
|
+
const c4 = (2 * Math.PI) / 3;
|
|
38
|
+
return t === 0 ? 0 : t === 1 ? 1 : -Math.pow(2, 10 * t - 10) * Math.sin((t * 10 - 10.75) * c4);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static easeOutElastic(t) {
|
|
42
|
+
const c4 = (2 * Math.PI) / 3;
|
|
43
|
+
return t === 0 ? 0 : t === 1 ? 1 : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static easeOutBounce(t) {
|
|
47
|
+
const n1 = 7.5625;
|
|
48
|
+
const d1 = 2.75;
|
|
49
|
+
if (t < 1 / d1) {
|
|
50
|
+
return n1 * t * t;
|
|
51
|
+
} else if (t < 2 / d1) {
|
|
52
|
+
return n1 * (t -= 1.5 / d1) * t + 0.75;
|
|
53
|
+
} else if (t < 2.5 / d1) {
|
|
54
|
+
return n1 * (t -= 2.25 / d1) * t + 0.9375;
|
|
55
|
+
} else {
|
|
56
|
+
return n1 * (t -= 2.625 / d1) * t + 0.984375;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static easeInBounce(t) {
|
|
61
|
+
return 1 - this.easeOutBounce(1 - t);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static easeInOutBounce(t) {
|
|
65
|
+
return t < 0.5
|
|
66
|
+
? (1 - this.easeOutBounce(1 - 2 * t)) / 2
|
|
67
|
+
: (1 + this.easeOutBounce(2 * t - 1)) / 2;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
static easeInExpo(t) {
|
|
71
|
+
return t === 0 ? 0 : Math.pow(2, 10 * t - 10);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static easeOutExpo(t) {
|
|
75
|
+
return t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static easeInOutExpo(t) {
|
|
79
|
+
return t === 0
|
|
80
|
+
? 0
|
|
81
|
+
: t === 1
|
|
82
|
+
? 1
|
|
83
|
+
: t < 0.5
|
|
84
|
+
? Math.pow(2, 20 * t - 10) / 2
|
|
85
|
+
: (2 - Math.pow(2, -20 * t + 10)) / 2;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static easeInCirc(t) {
|
|
89
|
+
return 1 - Math.sqrt(1 - Math.pow(t, 2));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static easeOutCirc(t) {
|
|
93
|
+
return Math.sqrt(1 - Math.pow(t - 1, 2));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
static easeInOutCirc(t) {
|
|
97
|
+
return t < 0.5
|
|
98
|
+
? (1 - Math.sqrt(1 - Math.pow(2 * t, 2))) / 2
|
|
99
|
+
: (Math.sqrt(1 - Math.pow(-2 * t + 2, 2)) + 1) / 2;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static cubicBezier(p0, p1, p2, p3, t) {
|
|
103
|
+
const mt = 1 - t;
|
|
104
|
+
return (
|
|
105
|
+
mt * mt * mt * p0 +
|
|
106
|
+
3 * mt * mt * t * p1 +
|
|
107
|
+
3 * mt * t * t * p2 +
|
|
108
|
+
t * t * t * p3
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
class Keyframe {
|
|
114
|
+
constructor(time, properties = {}, easing = 'linear') {
|
|
115
|
+
this.time = time;
|
|
116
|
+
this.properties = properties;
|
|
117
|
+
this.easing = easing;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
class AnimationTimeline {
|
|
122
|
+
constructor(duration = 1000) {
|
|
123
|
+
this.duration = duration;
|
|
124
|
+
this.keyframes = [];
|
|
125
|
+
this.currentTime = 0;
|
|
126
|
+
this.playing = false;
|
|
127
|
+
this.loop = false;
|
|
128
|
+
this.speed = 1;
|
|
129
|
+
this.onUpdate = null;
|
|
130
|
+
this.onComplete = null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Add keyframe to timeline
|
|
135
|
+
*/
|
|
136
|
+
addKeyframe(keyframe) {
|
|
137
|
+
this.keyframes.push(keyframe);
|
|
138
|
+
this.keyframes.sort((a, b) => a.time - b.time);
|
|
139
|
+
return this;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Add keyframe at time with properties
|
|
144
|
+
*/
|
|
145
|
+
at(time, properties, easing = 'linear') {
|
|
146
|
+
this.addKeyframe(new Keyframe(time, properties, easing));
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Play animation
|
|
152
|
+
*/
|
|
153
|
+
play() {
|
|
154
|
+
this.playing = true;
|
|
155
|
+
this.currentTime = 0;
|
|
156
|
+
return this;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Pause animation
|
|
161
|
+
*/
|
|
162
|
+
pause() {
|
|
163
|
+
this.playing = false;
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Resume animation
|
|
169
|
+
*/
|
|
170
|
+
resume() {
|
|
171
|
+
this.playing = true;
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Stop animation
|
|
177
|
+
*/
|
|
178
|
+
stop() {
|
|
179
|
+
this.playing = false;
|
|
180
|
+
this.currentTime = 0;
|
|
181
|
+
return this;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Update animation state
|
|
186
|
+
*/
|
|
187
|
+
update(deltaTime) {
|
|
188
|
+
if (!this.playing) return null;
|
|
189
|
+
|
|
190
|
+
this.currentTime += deltaTime * this.speed;
|
|
191
|
+
|
|
192
|
+
if (this.currentTime >= this.duration) {
|
|
193
|
+
if (this.loop) {
|
|
194
|
+
this.currentTime = 0;
|
|
195
|
+
} else {
|
|
196
|
+
this.playing = false;
|
|
197
|
+
this.currentTime = this.duration;
|
|
198
|
+
if (this.onComplete) this.onComplete();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const progress = this.currentTime / this.duration;
|
|
203
|
+
const properties = this.interpolateKeyframes(progress);
|
|
204
|
+
|
|
205
|
+
if (this.onUpdate) {
|
|
206
|
+
this.onUpdate(properties, progress);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return properties;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Interpolate between keyframes
|
|
214
|
+
*/
|
|
215
|
+
interpolateKeyframes(progress) {
|
|
216
|
+
const properties = {};
|
|
217
|
+
|
|
218
|
+
// Find surrounding keyframes
|
|
219
|
+
let before = null;
|
|
220
|
+
let after = null;
|
|
221
|
+
|
|
222
|
+
for (const keyframe of this.keyframes) {
|
|
223
|
+
if (keyframe.time / this.duration <= progress) {
|
|
224
|
+
before = keyframe;
|
|
225
|
+
}
|
|
226
|
+
if (keyframe.time / this.duration > progress && !after) {
|
|
227
|
+
after = keyframe;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (!before) {
|
|
232
|
+
return this.keyframes[0]?.properties || {};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (!after) {
|
|
236
|
+
return before.properties;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Interpolate between keyframes
|
|
240
|
+
const beforeTime = before.time / this.duration;
|
|
241
|
+
const afterTime = after.time / this.duration;
|
|
242
|
+
const rangeDuration = afterTime - beforeTime;
|
|
243
|
+
const relativeProgress = (progress - beforeTime) / rangeDuration;
|
|
244
|
+
|
|
245
|
+
const easing = this.getEasingFunction(before.easing);
|
|
246
|
+
const easedProgress = easing(Math.max(0, Math.min(1, relativeProgress)));
|
|
247
|
+
|
|
248
|
+
// Interpolate each property
|
|
249
|
+
for (const key in after.properties) {
|
|
250
|
+
const startValue = before.properties[key] || 0;
|
|
251
|
+
const endValue = after.properties[key];
|
|
252
|
+
|
|
253
|
+
if (typeof endValue === 'number') {
|
|
254
|
+
properties[key] = startValue + (endValue - startValue) * easedProgress;
|
|
255
|
+
} else {
|
|
256
|
+
properties[key] = easedProgress < 0.5 ? startValue : endValue;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return properties;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Get easing function
|
|
265
|
+
*/
|
|
266
|
+
getEasingFunction(name) {
|
|
267
|
+
const easingMap = {
|
|
268
|
+
linear: EasingFunctions.linear,
|
|
269
|
+
easeInQuad: EasingFunctions.easeInQuad,
|
|
270
|
+
easeOutQuad: EasingFunctions.easeOutQuad,
|
|
271
|
+
easeInOutQuad: EasingFunctions.easeInOutQuad,
|
|
272
|
+
easeInCubic: EasingFunctions.easeInCubic,
|
|
273
|
+
easeOutCubic: EasingFunctions.easeOutCubic,
|
|
274
|
+
easeInOutCubic: EasingFunctions.easeInOutCubic,
|
|
275
|
+
easeInElastic: EasingFunctions.easeInElastic,
|
|
276
|
+
easeOutElastic: EasingFunctions.easeOutElastic,
|
|
277
|
+
easeInBounce: EasingFunctions.easeInBounce,
|
|
278
|
+
easeOutBounce: EasingFunctions.easeOutBounce,
|
|
279
|
+
easeInOutBounce: EasingFunctions.easeInOutBounce,
|
|
280
|
+
easeInExpo: EasingFunctions.easeInExpo,
|
|
281
|
+
easeOutExpo: EasingFunctions.easeOutExpo,
|
|
282
|
+
easeInOutExpo: EasingFunctions.easeInOutExpo,
|
|
283
|
+
easeInCirc: EasingFunctions.easeInCirc,
|
|
284
|
+
easeOutCirc: EasingFunctions.easeOutCirc,
|
|
285
|
+
easeInOutCirc: EasingFunctions.easeInOutCirc
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
return easingMap[name] || EasingFunctions.linear;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
class AnimationSequence {
|
|
293
|
+
constructor() {
|
|
294
|
+
this.animations = [];
|
|
295
|
+
this.currentIndex = 0;
|
|
296
|
+
this.playing = false;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Add animation to sequence
|
|
301
|
+
*/
|
|
302
|
+
add(timeline) {
|
|
303
|
+
this.animations.push(timeline);
|
|
304
|
+
return this;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Play sequence
|
|
309
|
+
*/
|
|
310
|
+
play() {
|
|
311
|
+
this.playing = true;
|
|
312
|
+
this.currentIndex = 0;
|
|
313
|
+
if (this.animations[0]) {
|
|
314
|
+
this.animations[0].play();
|
|
315
|
+
}
|
|
316
|
+
return this;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Update sequence
|
|
321
|
+
*/
|
|
322
|
+
update(deltaTime) {
|
|
323
|
+
if (!this.playing || !this.animations[this.currentIndex]) return null;
|
|
324
|
+
|
|
325
|
+
const current = this.animations[this.currentIndex];
|
|
326
|
+
const result = current.update(deltaTime);
|
|
327
|
+
|
|
328
|
+
if (!current.playing) {
|
|
329
|
+
this.currentIndex++;
|
|
330
|
+
if (this.currentIndex < this.animations.length) {
|
|
331
|
+
this.animations[this.currentIndex].play();
|
|
332
|
+
} else {
|
|
333
|
+
this.playing = false;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return result;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
module.exports = {
|
|
342
|
+
EasingFunctions,
|
|
343
|
+
Keyframe,
|
|
344
|
+
AnimationTimeline,
|
|
345
|
+
AnimationSequence
|
|
346
|
+
};
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* STYL++ 3D & Effects Engine
|
|
3
|
+
* Advanced 3D transformations, particle effects, and visual filters
|
|
4
|
+
* Surpasses CSS 3D capabilities
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class Matrix3D {
|
|
8
|
+
constructor() {
|
|
9
|
+
// 4x4 identity matrix
|
|
10
|
+
this.matrix = [
|
|
11
|
+
[1, 0, 0, 0],
|
|
12
|
+
[0, 1, 0, 0],
|
|
13
|
+
[0, 0, 1, 0],
|
|
14
|
+
[0, 0, 0, 1]
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create identity matrix
|
|
20
|
+
*/
|
|
21
|
+
static identity() {
|
|
22
|
+
return new Matrix3D();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Translate
|
|
27
|
+
*/
|
|
28
|
+
translate(x, y, z = 0) {
|
|
29
|
+
const translation = [
|
|
30
|
+
[1, 0, 0, 0],
|
|
31
|
+
[0, 1, 0, 0],
|
|
32
|
+
[0, 0, 1, 0],
|
|
33
|
+
[x, y, z, 1]
|
|
34
|
+
];
|
|
35
|
+
this.multiply(translation);
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Rotate around X axis
|
|
41
|
+
*/
|
|
42
|
+
rotateX(angle) {
|
|
43
|
+
const rad = (angle * Math.PI) / 180;
|
|
44
|
+
const cos = Math.cos(rad);
|
|
45
|
+
const sin = Math.sin(rad);
|
|
46
|
+
const rotation = [
|
|
47
|
+
[1, 0, 0, 0],
|
|
48
|
+
[0, cos, -sin, 0],
|
|
49
|
+
[0, sin, cos, 0],
|
|
50
|
+
[0, 0, 0, 1]
|
|
51
|
+
];
|
|
52
|
+
this.multiply(rotation);
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Rotate around Y axis
|
|
58
|
+
*/
|
|
59
|
+
rotateY(angle) {
|
|
60
|
+
const rad = (angle * Math.PI) / 180;
|
|
61
|
+
const cos = Math.cos(rad);
|
|
62
|
+
const sin = Math.sin(rad);
|
|
63
|
+
const rotation = [
|
|
64
|
+
[cos, 0, sin, 0],
|
|
65
|
+
[0, 1, 0, 0],
|
|
66
|
+
[-sin, 0, cos, 0],
|
|
67
|
+
[0, 0, 0, 1]
|
|
68
|
+
];
|
|
69
|
+
this.multiply(rotation);
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Rotate around Z axis
|
|
75
|
+
*/
|
|
76
|
+
rotateZ(angle) {
|
|
77
|
+
const rad = (angle * Math.PI) / 180;
|
|
78
|
+
const cos = Math.cos(rad);
|
|
79
|
+
const sin = Math.sin(rad);
|
|
80
|
+
const rotation = [
|
|
81
|
+
[cos, -sin, 0, 0],
|
|
82
|
+
[sin, cos, 0, 0],
|
|
83
|
+
[0, 0, 1, 0],
|
|
84
|
+
[0, 0, 0, 1]
|
|
85
|
+
];
|
|
86
|
+
this.multiply(rotation);
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Scale
|
|
92
|
+
*/
|
|
93
|
+
scale(x, y = x, z = x) {
|
|
94
|
+
const scaling = [
|
|
95
|
+
[x, 0, 0, 0],
|
|
96
|
+
[0, y, 0, 0],
|
|
97
|
+
[0, 0, z, 0],
|
|
98
|
+
[0, 0, 0, 1]
|
|
99
|
+
];
|
|
100
|
+
this.multiply(scaling);
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Perspective (depth)
|
|
106
|
+
*/
|
|
107
|
+
perspective(depth) {
|
|
108
|
+
const perspective = [
|
|
109
|
+
[1, 0, 0, 0],
|
|
110
|
+
[0, 1, 0, 0],
|
|
111
|
+
[0, 0, 1, 0],
|
|
112
|
+
[0, 0, 1 / depth, 1]
|
|
113
|
+
];
|
|
114
|
+
this.multiply(perspective);
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Multiply matrices
|
|
120
|
+
*/
|
|
121
|
+
multiply(other) {
|
|
122
|
+
const result = [
|
|
123
|
+
[0, 0, 0, 0],
|
|
124
|
+
[0, 0, 0, 0],
|
|
125
|
+
[0, 0, 0, 0],
|
|
126
|
+
[0, 0, 0, 0]
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
for (let i = 0; i < 4; i++) {
|
|
130
|
+
for (let j = 0; j < 4; j++) {
|
|
131
|
+
for (let k = 0; k < 4; k++) {
|
|
132
|
+
result[i][j] += this.matrix[i][k] * other[k][j];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this.matrix = result;
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Convert to CSS matrix3d
|
|
143
|
+
*/
|
|
144
|
+
toCSS() {
|
|
145
|
+
const flat = this.matrix
|
|
146
|
+
.flat()
|
|
147
|
+
.map(v => v.toFixed(10))
|
|
148
|
+
.join(', ');
|
|
149
|
+
return `matrix3d(${flat})`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Convert to CSS transform string
|
|
154
|
+
*/
|
|
155
|
+
toString() {
|
|
156
|
+
return this.toCSS();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
class ParticleSystem {
|
|
161
|
+
constructor(config = {}) {
|
|
162
|
+
this.particles = [];
|
|
163
|
+
this.config = {
|
|
164
|
+
emission: config.emission || 10,
|
|
165
|
+
lifetime: config.lifetime || 1000,
|
|
166
|
+
velocityMin: config.velocityMin || -100,
|
|
167
|
+
velocityMax: config.velocityMax || 100,
|
|
168
|
+
gravityY: config.gravityY || 98,
|
|
169
|
+
friction: config.friction || 0.95,
|
|
170
|
+
...config
|
|
171
|
+
};
|
|
172
|
+
this.time = 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Emit particles
|
|
177
|
+
*/
|
|
178
|
+
emit(x, y, count = this.config.emission) {
|
|
179
|
+
for (let i = 0; i < count; i++) {
|
|
180
|
+
const angle = (Math.random() * Math.PI * 2);
|
|
181
|
+
const velocity = this.config.velocityMin +
|
|
182
|
+
Math.random() * (this.config.velocityMax - this.config.velocityMin);
|
|
183
|
+
|
|
184
|
+
this.particles.push({
|
|
185
|
+
x: x,
|
|
186
|
+
y: y,
|
|
187
|
+
vx: Math.cos(angle) * velocity,
|
|
188
|
+
vy: Math.sin(angle) * velocity,
|
|
189
|
+
age: 0,
|
|
190
|
+
lifetime: this.config.lifetime + Math.random() * 500,
|
|
191
|
+
color: this.config.color || `hsl(${Math.random() * 360}, 100%, 50%)`,
|
|
192
|
+
size: this.config.size || 5,
|
|
193
|
+
opacity: 1
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Update particles
|
|
200
|
+
*/
|
|
201
|
+
update(deltaTime) {
|
|
202
|
+
this.time += deltaTime;
|
|
203
|
+
|
|
204
|
+
this.particles = this.particles.filter(p => {
|
|
205
|
+
p.age += deltaTime;
|
|
206
|
+
|
|
207
|
+
if (p.age >= p.lifetime) {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Apply gravity
|
|
212
|
+
p.vy += this.config.gravityY * deltaTime;
|
|
213
|
+
|
|
214
|
+
// Apply friction
|
|
215
|
+
p.vx *= this.config.friction;
|
|
216
|
+
p.vy *= this.config.friction;
|
|
217
|
+
|
|
218
|
+
// Update position
|
|
219
|
+
p.x += p.vx * deltaTime;
|
|
220
|
+
p.y += p.vy * deltaTime;
|
|
221
|
+
|
|
222
|
+
// Fade out
|
|
223
|
+
p.opacity = 1 - p.age / p.lifetime;
|
|
224
|
+
|
|
225
|
+
return true;
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Get particles as SVG/Canvas drawing commands
|
|
231
|
+
*/
|
|
232
|
+
getDrawCommands() {
|
|
233
|
+
return this.particles.map(p => ({
|
|
234
|
+
x: p.x,
|
|
235
|
+
y: p.y,
|
|
236
|
+
size: p.size,
|
|
237
|
+
color: p.color,
|
|
238
|
+
opacity: p.opacity
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get particle count
|
|
244
|
+
*/
|
|
245
|
+
getCount() {
|
|
246
|
+
return this.particles.length;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
class AdvancedFilter {
|
|
251
|
+
/**
|
|
252
|
+
* Generate advanced CSS filters
|
|
253
|
+
*/
|
|
254
|
+
static blur(px) {
|
|
255
|
+
return `blur(${px}px)`;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
static brightness(percent) {
|
|
259
|
+
return `brightness(${percent}%)`;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
static contrast(percent) {
|
|
263
|
+
return `contrast(${percent}%)`;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
static grayscale(percent = 100) {
|
|
267
|
+
return `grayscale(${percent}%)`;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
static sepia(percent = 100) {
|
|
271
|
+
return `sepia(${percent}%)`;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
static hueRotate(degrees) {
|
|
275
|
+
return `hue-rotate(${degrees}deg)`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
static saturate(percent) {
|
|
279
|
+
return `saturate(${percent}%)`;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
static invert(percent = 100) {
|
|
283
|
+
return `invert(${percent}%)`;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
static dropShadow(x, y, blur, color) {
|
|
287
|
+
return `drop-shadow(${x}px ${y}px ${blur}px ${color})`;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Glass morphism effect
|
|
292
|
+
*/
|
|
293
|
+
static glassmorphism(blur = 10, opacity = 0.1) {
|
|
294
|
+
return {
|
|
295
|
+
backdrop: `blur(${blur}px)`,
|
|
296
|
+
background: `rgba(255, 255, 255, ${opacity})`,
|
|
297
|
+
border: '1px solid rgba(255, 255, 255, 0.2)'
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Neumorphism effect
|
|
303
|
+
*/
|
|
304
|
+
static neumorphism(direction = 'raised', color = '#e0e5ec') {
|
|
305
|
+
if (direction === 'raised') {
|
|
306
|
+
return {
|
|
307
|
+
boxShadow: `0.3em 0.3em 0.6em #c8d0e4, -0.2em -0.2em 0.5em #fff`,
|
|
308
|
+
background: color
|
|
309
|
+
};
|
|
310
|
+
} else {
|
|
311
|
+
return {
|
|
312
|
+
boxShadow: `inset 0.2em 0.2em 0.5em #c8d0e4, inset -0.2em -0.2em 0.5em #fff`,
|
|
313
|
+
background: color
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Glow effect
|
|
320
|
+
*/
|
|
321
|
+
static glow(color, blur = 20) {
|
|
322
|
+
return {
|
|
323
|
+
filter: `drop-shadow(0 0 ${blur}px ${color})`,
|
|
324
|
+
textShadow: `0 0 ${blur}px ${color}`
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Morphing animation
|
|
330
|
+
*/
|
|
331
|
+
static morphing(shapes) {
|
|
332
|
+
const result = {};
|
|
333
|
+
shapes.forEach((shape, i) => {
|
|
334
|
+
result[`morphing-${i}`] = shape;
|
|
335
|
+
});
|
|
336
|
+
return result;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
module.exports = {
|
|
341
|
+
Matrix3D,
|
|
342
|
+
ParticleSystem,
|
|
343
|
+
AdvancedFilter
|
|
344
|
+
};
|