fluxo-animation 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/LICENSE +21 -0
- package/README.md +151 -0
- package/dist/index.cjs +1265 -0
- package/dist/index.d.cts +261 -0
- package/dist/index.d.ts +261 -0
- package/dist/index.global.js +1248 -0
- package/dist/index.js +1223 -0
- package/package.json +39 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ScrollTrigger: () => ScrollTrigger,
|
|
24
|
+
Timeline: () => Timeline,
|
|
25
|
+
Tween: () => Tween,
|
|
26
|
+
drawSVG: () => drawSVG,
|
|
27
|
+
easings: () => easings,
|
|
28
|
+
explodeOnScroll: () => explodeOnScroll,
|
|
29
|
+
fluxo: () => fluxo,
|
|
30
|
+
implodeOnScroll: () => implodeOnScroll,
|
|
31
|
+
magnetic: () => magnetic,
|
|
32
|
+
resolveTargets: () => resolveTargets,
|
|
33
|
+
revealText: () => revealText,
|
|
34
|
+
scrollReveal: () => scrollReveal,
|
|
35
|
+
slidingMenu: () => slidingMenu,
|
|
36
|
+
splitText: () => splitText,
|
|
37
|
+
ticker: () => ticker,
|
|
38
|
+
tilt: () => tilt
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(index_exports);
|
|
41
|
+
|
|
42
|
+
// src/ticker.ts
|
|
43
|
+
var Ticker = class {
|
|
44
|
+
callbacks = /* @__PURE__ */ new Set();
|
|
45
|
+
rafId = null;
|
|
46
|
+
lastTime = 0;
|
|
47
|
+
time = 0;
|
|
48
|
+
constructor() {
|
|
49
|
+
this.tick = this.tick.bind(this);
|
|
50
|
+
}
|
|
51
|
+
add(cb) {
|
|
52
|
+
this.callbacks.add(cb);
|
|
53
|
+
if (this.rafId === null) {
|
|
54
|
+
this.start();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
remove(cb) {
|
|
58
|
+
this.callbacks.delete(cb);
|
|
59
|
+
if (this.callbacks.size === 0 && this.rafId !== null) {
|
|
60
|
+
this.stop();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
start() {
|
|
64
|
+
this.lastTime = performance.now();
|
|
65
|
+
this.rafId = requestAnimationFrame(this.tick);
|
|
66
|
+
}
|
|
67
|
+
stop() {
|
|
68
|
+
if (this.rafId !== null) {
|
|
69
|
+
cancelAnimationFrame(this.rafId);
|
|
70
|
+
this.rafId = null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
tick(now) {
|
|
74
|
+
const dt = (now - this.lastTime) / 1e3;
|
|
75
|
+
this.lastTime = now;
|
|
76
|
+
this.time += dt;
|
|
77
|
+
const activeCallbacks = Array.from(this.callbacks);
|
|
78
|
+
for (const cb of activeCallbacks) {
|
|
79
|
+
cb(this.time, dt);
|
|
80
|
+
}
|
|
81
|
+
if (this.callbacks.size > 0) {
|
|
82
|
+
this.rafId = requestAnimationFrame(this.tick);
|
|
83
|
+
} else {
|
|
84
|
+
this.rafId = null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
var ticker = new Ticker();
|
|
89
|
+
|
|
90
|
+
// src/easings.ts
|
|
91
|
+
var easings = {
|
|
92
|
+
none: (t) => t,
|
|
93
|
+
linear: (t) => t,
|
|
94
|
+
"slow.in": (t) => t * t,
|
|
95
|
+
"slow.out": (t) => t * (2 - t),
|
|
96
|
+
"slow.inOut": (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2,
|
|
97
|
+
"medium.in": (t) => t * t * t,
|
|
98
|
+
"medium.out": (t) => 1 - Math.pow(1 - t, 3),
|
|
99
|
+
"medium.inOut": (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2,
|
|
100
|
+
"fast.in": (t) => t * t * t * t,
|
|
101
|
+
"fast.out": (t) => 1 - Math.pow(1 - t, 4),
|
|
102
|
+
"fast.inOut": (t) => t < 0.5 ? 8 * t * t * t * t : 1 - Math.pow(-2 * t + 2, 4) / 2,
|
|
103
|
+
"veryFast.in": (t) => t * t * t * t * t,
|
|
104
|
+
"veryFast.out": (t) => 1 - Math.pow(1 - t, 5),
|
|
105
|
+
"veryFast.inOut": (t) => t < 0.5 ? 16 * t * t * t * t * t : 1 - Math.pow(-2 * t + 2, 5) / 2
|
|
106
|
+
};
|
|
107
|
+
function getEasing(ease) {
|
|
108
|
+
if (!ease) return easings["slow.out"];
|
|
109
|
+
if (typeof ease === "function") return ease;
|
|
110
|
+
return easings[ease] || easings["slow.out"];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/utils.ts
|
|
114
|
+
function resolveTargets(target) {
|
|
115
|
+
if (!target) return [];
|
|
116
|
+
if (typeof target === "string") {
|
|
117
|
+
if (typeof document !== "undefined") {
|
|
118
|
+
return Array.from(document.querySelectorAll(target));
|
|
119
|
+
}
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
if (Array.isArray(target)) {
|
|
123
|
+
return target;
|
|
124
|
+
}
|
|
125
|
+
if (typeof NodeList !== "undefined" && target instanceof NodeList) {
|
|
126
|
+
return Array.from(target);
|
|
127
|
+
}
|
|
128
|
+
if (typeof HTMLCollection !== "undefined" && target instanceof HTMLCollection) {
|
|
129
|
+
return Array.from(target);
|
|
130
|
+
}
|
|
131
|
+
return [target];
|
|
132
|
+
}
|
|
133
|
+
function splitText(target, options = {}) {
|
|
134
|
+
const targets = resolveTargets(target);
|
|
135
|
+
const type = options.type || "chars";
|
|
136
|
+
const resultSpans = [];
|
|
137
|
+
targets.forEach((el) => {
|
|
138
|
+
if (!(el instanceof HTMLElement)) return;
|
|
139
|
+
const originalText = el.textContent || "";
|
|
140
|
+
el.innerHTML = "";
|
|
141
|
+
if (type === "chars") {
|
|
142
|
+
const chars = originalText.split("");
|
|
143
|
+
chars.forEach((char) => {
|
|
144
|
+
if (char === " ") {
|
|
145
|
+
el.appendChild(document.createTextNode(" "));
|
|
146
|
+
} else {
|
|
147
|
+
const span = document.createElement("span");
|
|
148
|
+
span.className = "fluxo-char";
|
|
149
|
+
span.style.display = "inline-block";
|
|
150
|
+
span.textContent = char;
|
|
151
|
+
el.appendChild(span);
|
|
152
|
+
resultSpans.push(span);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
} else {
|
|
156
|
+
const words = originalText.split(" ");
|
|
157
|
+
words.forEach((word, index) => {
|
|
158
|
+
if (index > 0) {
|
|
159
|
+
el.appendChild(document.createTextNode(" "));
|
|
160
|
+
}
|
|
161
|
+
const span = document.createElement("span");
|
|
162
|
+
span.className = "fluxo-word";
|
|
163
|
+
span.style.display = "inline-block";
|
|
164
|
+
span.textContent = word;
|
|
165
|
+
el.appendChild(span);
|
|
166
|
+
resultSpans.push(span);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
return resultSpans;
|
|
171
|
+
}
|
|
172
|
+
function drawSVG(target, vars) {
|
|
173
|
+
const targets = resolveTargets(target);
|
|
174
|
+
const path = targets.length > 0 ? targets[0] : null;
|
|
175
|
+
if (!path || typeof path.getTotalLength !== "function") {
|
|
176
|
+
throw new Error(
|
|
177
|
+
"drawSVG: Target must be a valid SVG element with getTotalLength (such as <path>)"
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
const length = path.getTotalLength();
|
|
181
|
+
path.style.strokeDasharray = String(length);
|
|
182
|
+
path.style.strokeDashoffset = String(length);
|
|
183
|
+
return new Tween(path, {
|
|
184
|
+
strokeDashoffset: 0,
|
|
185
|
+
...vars
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/tween.ts
|
|
190
|
+
var TRANSFORM_KEYS = /* @__PURE__ */ new Set(["x", "y", "rotation", "scale"]);
|
|
191
|
+
var RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
192
|
+
"duration",
|
|
193
|
+
"delay",
|
|
194
|
+
"ease",
|
|
195
|
+
"autoPlay",
|
|
196
|
+
"repeat",
|
|
197
|
+
"alternate",
|
|
198
|
+
"onStart",
|
|
199
|
+
"onUpdate",
|
|
200
|
+
"onComplete",
|
|
201
|
+
"onRepeat"
|
|
202
|
+
]);
|
|
203
|
+
var Tween = class {
|
|
204
|
+
target;
|
|
205
|
+
vars;
|
|
206
|
+
duration;
|
|
207
|
+
delay;
|
|
208
|
+
ease;
|
|
209
|
+
fromVars;
|
|
210
|
+
isFrom = false;
|
|
211
|
+
playhead = 0;
|
|
212
|
+
reversed = false;
|
|
213
|
+
started = false;
|
|
214
|
+
completed = false;
|
|
215
|
+
repeatCount = 0;
|
|
216
|
+
propTweens = [];
|
|
217
|
+
constructor(target, vars, fromVars, isFrom = false) {
|
|
218
|
+
const resolved = resolveTargets(target);
|
|
219
|
+
this.target = resolved.length > 0 ? resolved[0] : null;
|
|
220
|
+
this.vars = vars;
|
|
221
|
+
this.fromVars = fromVars;
|
|
222
|
+
this.isFrom = isFrom;
|
|
223
|
+
this.duration = vars.duration !== void 0 ? vars.duration : 0.5;
|
|
224
|
+
this.delay = vars.delay !== void 0 ? vars.delay : 0;
|
|
225
|
+
this.ease = getEasing(vars.ease);
|
|
226
|
+
this.update = this.update.bind(this);
|
|
227
|
+
const autoPlay = vars.autoPlay !== false;
|
|
228
|
+
if (this.target) {
|
|
229
|
+
if (this.isFrom || this.fromVars) {
|
|
230
|
+
this.initProperties();
|
|
231
|
+
this.started = true;
|
|
232
|
+
}
|
|
233
|
+
if (autoPlay) {
|
|
234
|
+
ticker.add(this.update);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
initProperties() {
|
|
239
|
+
this.propTweens = [];
|
|
240
|
+
const isDOM = this.target instanceof HTMLElement || typeof SVGElement !== "undefined" && this.target instanceof SVGElement;
|
|
241
|
+
let transformState = null;
|
|
242
|
+
if (isDOM) {
|
|
243
|
+
transformState = this.getTransformState(this.target);
|
|
244
|
+
}
|
|
245
|
+
for (const key in this.vars) {
|
|
246
|
+
if (RESERVED_KEYS.has(key)) continue;
|
|
247
|
+
const endValueRaw = this.vars[key];
|
|
248
|
+
const parsedEnd = this.parseValue(endValueRaw);
|
|
249
|
+
let currentVal = 0;
|
|
250
|
+
let unit = parsedEnd.unit;
|
|
251
|
+
const isTransform = isDOM && TRANSFORM_KEYS.has(key);
|
|
252
|
+
if (isTransform && transformState) {
|
|
253
|
+
currentVal = transformState[key];
|
|
254
|
+
} else if (isDOM) {
|
|
255
|
+
const computedStyle = window.getComputedStyle(this.target);
|
|
256
|
+
const styleVal = computedStyle[key] || this.target.style[key];
|
|
257
|
+
const parsedStart = this.parseValue(styleVal);
|
|
258
|
+
currentVal = parsedStart.value;
|
|
259
|
+
if (unit === "" && parsedStart.unit !== "") {
|
|
260
|
+
unit = parsedStart.unit;
|
|
261
|
+
}
|
|
262
|
+
} else {
|
|
263
|
+
currentVal = typeof this.target[key] === "number" ? this.target[key] : 0;
|
|
264
|
+
}
|
|
265
|
+
let startValue = 0;
|
|
266
|
+
let endValue = 0;
|
|
267
|
+
if (this.fromVars) {
|
|
268
|
+
const parsedFrom = this.parseValue(this.fromVars[key]);
|
|
269
|
+
startValue = parsedFrom.value;
|
|
270
|
+
endValue = parsedEnd.value;
|
|
271
|
+
unit = parsedEnd.unit || parsedFrom.unit || unit;
|
|
272
|
+
} else if (this.isFrom) {
|
|
273
|
+
startValue = parsedEnd.value;
|
|
274
|
+
endValue = currentVal;
|
|
275
|
+
} else {
|
|
276
|
+
startValue = currentVal;
|
|
277
|
+
endValue = parsedEnd.value;
|
|
278
|
+
}
|
|
279
|
+
this.propTweens.push({
|
|
280
|
+
key,
|
|
281
|
+
isTransform,
|
|
282
|
+
start: startValue,
|
|
283
|
+
end: endValue,
|
|
284
|
+
unit
|
|
285
|
+
});
|
|
286
|
+
if (this.isFrom || this.fromVars) {
|
|
287
|
+
if (isTransform && transformState) {
|
|
288
|
+
transformState[key] = startValue;
|
|
289
|
+
} else if (isDOM) {
|
|
290
|
+
this.target.style[key] = startValue + unit;
|
|
291
|
+
} else {
|
|
292
|
+
this.target[key] = startValue;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if ((this.isFrom || this.fromVars) && transformState && isDOM) {
|
|
297
|
+
this.applyTransform(this.target, transformState);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
parseValue(val) {
|
|
301
|
+
if (typeof val === "number") {
|
|
302
|
+
return { value: val, unit: "" };
|
|
303
|
+
}
|
|
304
|
+
const num = parseFloat(val);
|
|
305
|
+
if (isNaN(num)) {
|
|
306
|
+
return { value: 0, unit: "" };
|
|
307
|
+
}
|
|
308
|
+
const unit = String(val).replace(/^[-\d.]+/, "");
|
|
309
|
+
return { value: num, unit };
|
|
310
|
+
}
|
|
311
|
+
getTransformState(el) {
|
|
312
|
+
if (!el._fluxoTransform) {
|
|
313
|
+
el._fluxoTransform = { x: 0, y: 0, rotation: 0, scale: 1 };
|
|
314
|
+
}
|
|
315
|
+
return el._fluxoTransform;
|
|
316
|
+
}
|
|
317
|
+
applyTransform(el, state) {
|
|
318
|
+
el.style.transform = `translate3d(${state.x}px, ${state.y}px, 0px) rotate(${state.rotation}deg) scale(${state.scale})`;
|
|
319
|
+
}
|
|
320
|
+
play() {
|
|
321
|
+
this.reversed = false;
|
|
322
|
+
this.completed = false;
|
|
323
|
+
const maxTime = this.duration + this.delay;
|
|
324
|
+
if (this.playhead >= maxTime) {
|
|
325
|
+
this.playhead = 0;
|
|
326
|
+
this.repeatCount = 0;
|
|
327
|
+
}
|
|
328
|
+
ticker.add(this.update);
|
|
329
|
+
}
|
|
330
|
+
reverse() {
|
|
331
|
+
this.reversed = true;
|
|
332
|
+
this.completed = false;
|
|
333
|
+
if (this.playhead <= 0) {
|
|
334
|
+
this.playhead = this.duration + this.delay;
|
|
335
|
+
this.repeatCount = 0;
|
|
336
|
+
}
|
|
337
|
+
ticker.add(this.update);
|
|
338
|
+
}
|
|
339
|
+
pause() {
|
|
340
|
+
ticker.remove(this.update);
|
|
341
|
+
}
|
|
342
|
+
render(time) {
|
|
343
|
+
let progress = 0;
|
|
344
|
+
if (time >= this.delay) {
|
|
345
|
+
const activeTime = time - this.delay;
|
|
346
|
+
progress = this.duration > 0 ? activeTime / this.duration : 1;
|
|
347
|
+
if (progress > 1) progress = 1;
|
|
348
|
+
}
|
|
349
|
+
if (!this.started && time >= this.delay) {
|
|
350
|
+
this.started = true;
|
|
351
|
+
this.initProperties();
|
|
352
|
+
if (this.vars.onStart) {
|
|
353
|
+
this.vars.onStart();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const easedProgress = this.ease(progress);
|
|
357
|
+
let hasTransform = false;
|
|
358
|
+
const transformState = this.target instanceof HTMLElement || typeof SVGElement !== "undefined" && this.target instanceof SVGElement ? this.getTransformState(this.target) : null;
|
|
359
|
+
for (const pt of this.propTweens) {
|
|
360
|
+
const currentVal = pt.start + (pt.end - pt.start) * easedProgress;
|
|
361
|
+
if (pt.isTransform && transformState) {
|
|
362
|
+
transformState[pt.key] = currentVal;
|
|
363
|
+
hasTransform = true;
|
|
364
|
+
} else if (this.target.style !== void 0) {
|
|
365
|
+
this.target.style[pt.key] = currentVal + pt.unit;
|
|
366
|
+
} else {
|
|
367
|
+
this.target[pt.key] = currentVal;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (hasTransform && transformState) {
|
|
371
|
+
this.applyTransform(this.target, transformState);
|
|
372
|
+
}
|
|
373
|
+
if (this.vars.onUpdate) {
|
|
374
|
+
this.vars.onUpdate();
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
update(totalTime, dt) {
|
|
378
|
+
if (this.completed) return;
|
|
379
|
+
this.playhead += this.reversed ? -dt : dt;
|
|
380
|
+
const maxTime = this.duration + this.delay;
|
|
381
|
+
const repeatOption = this.vars.repeat !== void 0 ? this.vars.repeat : 0;
|
|
382
|
+
const alternateOption = this.vars.alternate === true;
|
|
383
|
+
if (this.reversed) {
|
|
384
|
+
if (this.playhead <= this.delay) {
|
|
385
|
+
if (repeatOption === -1 || this.repeatCount < repeatOption) {
|
|
386
|
+
this.repeatCount++;
|
|
387
|
+
if (this.vars.onRepeat) {
|
|
388
|
+
this.vars.onRepeat();
|
|
389
|
+
}
|
|
390
|
+
if (alternateOption) {
|
|
391
|
+
this.reversed = false;
|
|
392
|
+
this.playhead = this.delay;
|
|
393
|
+
} else {
|
|
394
|
+
this.playhead = maxTime;
|
|
395
|
+
}
|
|
396
|
+
} else {
|
|
397
|
+
this.playhead = 0;
|
|
398
|
+
this.completed = true;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
} else {
|
|
402
|
+
if (this.playhead >= maxTime) {
|
|
403
|
+
if (repeatOption === -1 || this.repeatCount < repeatOption) {
|
|
404
|
+
this.repeatCount++;
|
|
405
|
+
if (this.vars.onRepeat) {
|
|
406
|
+
this.vars.onRepeat();
|
|
407
|
+
}
|
|
408
|
+
if (alternateOption) {
|
|
409
|
+
this.reversed = true;
|
|
410
|
+
this.playhead = maxTime;
|
|
411
|
+
} else {
|
|
412
|
+
this.playhead = this.delay;
|
|
413
|
+
}
|
|
414
|
+
} else {
|
|
415
|
+
this.playhead = maxTime;
|
|
416
|
+
this.completed = true;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
this.render(this.playhead);
|
|
421
|
+
if (this.completed) {
|
|
422
|
+
ticker.remove(this.update);
|
|
423
|
+
if (this.vars.onComplete) {
|
|
424
|
+
this.vars.onComplete();
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
kill() {
|
|
429
|
+
ticker.remove(this.update);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
// src/timeline.ts
|
|
434
|
+
var Timeline = class {
|
|
435
|
+
children = [];
|
|
436
|
+
vars;
|
|
437
|
+
duration = 0;
|
|
438
|
+
delay;
|
|
439
|
+
playhead = 0;
|
|
440
|
+
reversed = false;
|
|
441
|
+
started = false;
|
|
442
|
+
completed = false;
|
|
443
|
+
isPlaying = false;
|
|
444
|
+
repeatCount = 0;
|
|
445
|
+
constructor(vars = {}) {
|
|
446
|
+
this.vars = vars;
|
|
447
|
+
this.delay = vars.delay !== void 0 ? vars.delay : 0;
|
|
448
|
+
this.update = this.update.bind(this);
|
|
449
|
+
if (!vars.paused) {
|
|
450
|
+
this.play();
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Adds an existing, externally created Tween instance to this timeline.
|
|
455
|
+
* Useful for inserting custom tweens like fluxo.drawSVG().
|
|
456
|
+
*
|
|
457
|
+
* @param tween The Tween instance to add.
|
|
458
|
+
* @param position Optional position key (number, relative offset like "+=0.5", or alignment like "<").
|
|
459
|
+
*/
|
|
460
|
+
add(tween, position) {
|
|
461
|
+
tween.pause();
|
|
462
|
+
const baseTime = this.parsePosition(position);
|
|
463
|
+
this.addTween(tween, baseTime);
|
|
464
|
+
return this;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Adds .to() tweens to the timeline.
|
|
468
|
+
*/
|
|
469
|
+
to(target, vars, position) {
|
|
470
|
+
const targets = resolveTargets(target);
|
|
471
|
+
const baseTime = this.parsePosition(position);
|
|
472
|
+
const stagger = vars.stagger || 0;
|
|
473
|
+
const tweenVars = { ...vars };
|
|
474
|
+
delete tweenVars.stagger;
|
|
475
|
+
targets.forEach((t, i) => {
|
|
476
|
+
const tween = new Tween(t, { ...tweenVars, autoPlay: false });
|
|
477
|
+
this.addTween(tween, baseTime + i * stagger);
|
|
478
|
+
});
|
|
479
|
+
return this;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Adds .from() tweens to the timeline.
|
|
483
|
+
*/
|
|
484
|
+
from(target, vars, position) {
|
|
485
|
+
const targets = resolveTargets(target);
|
|
486
|
+
const baseTime = this.parsePosition(position);
|
|
487
|
+
const stagger = vars.stagger || 0;
|
|
488
|
+
const tweenVars = { ...vars };
|
|
489
|
+
delete tweenVars.stagger;
|
|
490
|
+
targets.forEach((t, i) => {
|
|
491
|
+
const tween = new Tween(
|
|
492
|
+
t,
|
|
493
|
+
{ ...tweenVars, autoPlay: false },
|
|
494
|
+
void 0,
|
|
495
|
+
true
|
|
496
|
+
);
|
|
497
|
+
this.addTween(tween, baseTime + i * stagger);
|
|
498
|
+
});
|
|
499
|
+
return this;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Adds .fromTo() tweens to the timeline.
|
|
503
|
+
*/
|
|
504
|
+
fromTo(target, fromVars, toVars, position) {
|
|
505
|
+
const targets = resolveTargets(target);
|
|
506
|
+
const baseTime = this.parsePosition(position);
|
|
507
|
+
const stagger = toVars.stagger || 0;
|
|
508
|
+
const tweenVars = { ...toVars };
|
|
509
|
+
delete tweenVars.stagger;
|
|
510
|
+
targets.forEach((t, i) => {
|
|
511
|
+
const tween = new Tween(t, { ...tweenVars, autoPlay: false }, fromVars);
|
|
512
|
+
this.addTween(tween, baseTime + i * stagger);
|
|
513
|
+
});
|
|
514
|
+
return this;
|
|
515
|
+
}
|
|
516
|
+
play() {
|
|
517
|
+
this.reversed = false;
|
|
518
|
+
this.completed = false;
|
|
519
|
+
const maxTime = this.duration + this.delay;
|
|
520
|
+
if (this.playhead >= maxTime) {
|
|
521
|
+
this.playhead = 0;
|
|
522
|
+
this.repeatCount = 0;
|
|
523
|
+
}
|
|
524
|
+
this.isPlaying = true;
|
|
525
|
+
ticker.add(this.update);
|
|
526
|
+
}
|
|
527
|
+
reverse() {
|
|
528
|
+
this.reversed = true;
|
|
529
|
+
this.completed = false;
|
|
530
|
+
if (this.playhead <= 0) {
|
|
531
|
+
this.playhead = this.duration + this.delay;
|
|
532
|
+
this.repeatCount = 0;
|
|
533
|
+
}
|
|
534
|
+
this.isPlaying = true;
|
|
535
|
+
ticker.add(this.update);
|
|
536
|
+
}
|
|
537
|
+
pause() {
|
|
538
|
+
if (!this.isPlaying) return;
|
|
539
|
+
this.isPlaying = false;
|
|
540
|
+
ticker.remove(this.update);
|
|
541
|
+
}
|
|
542
|
+
kill() {
|
|
543
|
+
this.isPlaying = false;
|
|
544
|
+
ticker.remove(this.update);
|
|
545
|
+
for (const child of this.children) {
|
|
546
|
+
child.tween.kill();
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
parsePosition(position) {
|
|
550
|
+
let startTime = this.duration;
|
|
551
|
+
const prevChild = this.children[this.children.length - 1];
|
|
552
|
+
if (position !== void 0) {
|
|
553
|
+
if (typeof position === "number") {
|
|
554
|
+
startTime = position;
|
|
555
|
+
} else if (typeof position === "string") {
|
|
556
|
+
if (position.startsWith("+=")) {
|
|
557
|
+
const val = parseFloat(position.slice(2));
|
|
558
|
+
startTime = this.duration + (isNaN(val) ? 0 : val);
|
|
559
|
+
} else if (position.startsWith("-=")) {
|
|
560
|
+
const val = parseFloat(position.slice(2));
|
|
561
|
+
startTime = this.duration - (isNaN(val) ? 0 : val);
|
|
562
|
+
} else if (position === "<") {
|
|
563
|
+
startTime = prevChild ? prevChild.startTime : 0;
|
|
564
|
+
} else if (position.startsWith("<")) {
|
|
565
|
+
const offsetStr = position.slice(1);
|
|
566
|
+
const baseTime = prevChild ? prevChild.startTime : 0;
|
|
567
|
+
if (offsetStr.startsWith("+=")) {
|
|
568
|
+
const val = parseFloat(offsetStr.slice(2));
|
|
569
|
+
startTime = baseTime + (isNaN(val) ? 0 : val);
|
|
570
|
+
} else if (offsetStr.startsWith("-=")) {
|
|
571
|
+
const val = parseFloat(offsetStr.slice(2));
|
|
572
|
+
startTime = baseTime - (isNaN(val) ? 0 : val);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return startTime;
|
|
578
|
+
}
|
|
579
|
+
addTween(tween, startTime) {
|
|
580
|
+
const tweenDuration = tween.duration + tween.delay;
|
|
581
|
+
const endTime = startTime + tweenDuration;
|
|
582
|
+
this.children.push({
|
|
583
|
+
tween,
|
|
584
|
+
startTime,
|
|
585
|
+
endTime
|
|
586
|
+
});
|
|
587
|
+
this.duration = Math.max(this.duration, endTime);
|
|
588
|
+
}
|
|
589
|
+
render(time) {
|
|
590
|
+
let activeTime = 0;
|
|
591
|
+
if (time >= this.delay) {
|
|
592
|
+
activeTime = time - this.delay;
|
|
593
|
+
}
|
|
594
|
+
if (!this.started && time >= this.delay) {
|
|
595
|
+
this.started = true;
|
|
596
|
+
if (this.vars.onStart) {
|
|
597
|
+
this.vars.onStart();
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
for (const child of this.children) {
|
|
601
|
+
const localTime = activeTime - child.startTime;
|
|
602
|
+
child.tween.render(localTime);
|
|
603
|
+
}
|
|
604
|
+
if (this.vars.onUpdate) {
|
|
605
|
+
this.vars.onUpdate();
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
update(totalTime, dt) {
|
|
609
|
+
if (this.completed) return;
|
|
610
|
+
this.playhead += this.reversed ? -dt : dt;
|
|
611
|
+
const maxTime = this.duration + this.delay;
|
|
612
|
+
const repeatOption = this.vars.repeat !== void 0 ? this.vars.repeat : 0;
|
|
613
|
+
const alternateOption = this.vars.alternate === true;
|
|
614
|
+
if (this.reversed) {
|
|
615
|
+
if (this.playhead <= this.delay) {
|
|
616
|
+
if (repeatOption === -1 || this.repeatCount < repeatOption) {
|
|
617
|
+
this.repeatCount++;
|
|
618
|
+
if (this.vars.onRepeat) {
|
|
619
|
+
this.vars.onRepeat();
|
|
620
|
+
}
|
|
621
|
+
if (alternateOption) {
|
|
622
|
+
this.reversed = false;
|
|
623
|
+
this.playhead = this.delay;
|
|
624
|
+
} else {
|
|
625
|
+
this.playhead = maxTime;
|
|
626
|
+
}
|
|
627
|
+
} else {
|
|
628
|
+
this.playhead = 0;
|
|
629
|
+
this.completed = true;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
} else {
|
|
633
|
+
if (this.playhead >= maxTime) {
|
|
634
|
+
if (repeatOption === -1 || this.repeatCount < repeatOption) {
|
|
635
|
+
this.repeatCount++;
|
|
636
|
+
if (this.vars.onRepeat) {
|
|
637
|
+
this.vars.onRepeat();
|
|
638
|
+
}
|
|
639
|
+
if (alternateOption) {
|
|
640
|
+
this.reversed = true;
|
|
641
|
+
this.playhead = maxTime;
|
|
642
|
+
} else {
|
|
643
|
+
this.playhead = this.delay;
|
|
644
|
+
}
|
|
645
|
+
} else {
|
|
646
|
+
this.playhead = maxTime;
|
|
647
|
+
this.completed = true;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
this.render(this.playhead);
|
|
652
|
+
if (this.completed) {
|
|
653
|
+
this.isPlaying = false;
|
|
654
|
+
ticker.remove(this.update);
|
|
655
|
+
if (this.vars.onComplete) {
|
|
656
|
+
this.vars.onComplete();
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
// src/scrollTrigger.ts
|
|
663
|
+
var ScrollTrigger = class _ScrollTrigger {
|
|
664
|
+
static instances = [];
|
|
665
|
+
animation;
|
|
666
|
+
triggerEl;
|
|
667
|
+
vars;
|
|
668
|
+
startScroll = 0;
|
|
669
|
+
endScroll = 0;
|
|
670
|
+
hasTriggered = false;
|
|
671
|
+
constructor(animation, vars) {
|
|
672
|
+
this.animation = animation;
|
|
673
|
+
this.vars = vars;
|
|
674
|
+
_ScrollTrigger.instances.push(this);
|
|
675
|
+
const resolved = resolveTargets(vars.trigger);
|
|
676
|
+
if (resolved.length === 0) {
|
|
677
|
+
throw new Error(
|
|
678
|
+
`ScrollTrigger: Target trigger element not found for "${vars.trigger}"`
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
this.triggerEl = resolved[0];
|
|
682
|
+
this.onScroll = this.onScroll.bind(this);
|
|
683
|
+
this.refresh = this.refresh.bind(this);
|
|
684
|
+
this.refresh();
|
|
685
|
+
window.addEventListener("scroll", this.onScroll, { passive: true });
|
|
686
|
+
window.addEventListener("resize", this.refresh, { passive: true });
|
|
687
|
+
this.onScroll();
|
|
688
|
+
}
|
|
689
|
+
refresh() {
|
|
690
|
+
const rect = this.triggerEl.getBoundingClientRect();
|
|
691
|
+
const docScrollY = window.scrollY;
|
|
692
|
+
const elTop = rect.top + docScrollY;
|
|
693
|
+
const elHeight = rect.height;
|
|
694
|
+
const startStr = this.vars.start || "top bottom";
|
|
695
|
+
this.startScroll = this.calculateScrollPos(
|
|
696
|
+
startStr,
|
|
697
|
+
elTop,
|
|
698
|
+
elHeight,
|
|
699
|
+
"top",
|
|
700
|
+
"bottom"
|
|
701
|
+
);
|
|
702
|
+
const endStr = this.vars.end || "bottom top";
|
|
703
|
+
this.endScroll = this.calculateScrollPos(
|
|
704
|
+
endStr,
|
|
705
|
+
elTop,
|
|
706
|
+
elHeight,
|
|
707
|
+
"bottom",
|
|
708
|
+
"top"
|
|
709
|
+
);
|
|
710
|
+
if (this.endScroll <= this.startScroll) {
|
|
711
|
+
this.endScroll = this.startScroll + 1;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
calculateScrollPos(posStr, elTop, elHeight, defaultElPart, defaultVPart) {
|
|
715
|
+
const parts = posStr.split(" ");
|
|
716
|
+
const elPart = parts[0] || defaultElPart;
|
|
717
|
+
const vPart = parts[1] || defaultVPart;
|
|
718
|
+
let elOffset = 0;
|
|
719
|
+
if (elPart === "top") elOffset = 0;
|
|
720
|
+
else if (elPart === "center") elOffset = elHeight / 2;
|
|
721
|
+
else if (elPart === "bottom") elOffset = elHeight;
|
|
722
|
+
else if (elPart.endsWith("%")) {
|
|
723
|
+
elOffset = parseFloat(elPart) / 100 * elHeight;
|
|
724
|
+
} else {
|
|
725
|
+
elOffset = parseFloat(elPart) || 0;
|
|
726
|
+
}
|
|
727
|
+
let vOffset = 0;
|
|
728
|
+
const vh = window.innerHeight;
|
|
729
|
+
if (vPart === "top") vOffset = 0;
|
|
730
|
+
else if (vPart === "center") vOffset = vh / 2;
|
|
731
|
+
else if (vPart === "bottom") vOffset = vh;
|
|
732
|
+
else if (vPart.endsWith("%")) {
|
|
733
|
+
vOffset = parseFloat(vPart) / 100 * vh;
|
|
734
|
+
} else {
|
|
735
|
+
vOffset = parseFloat(vPart) || 0;
|
|
736
|
+
}
|
|
737
|
+
return elTop + elOffset - vOffset;
|
|
738
|
+
}
|
|
739
|
+
onScroll() {
|
|
740
|
+
const scrollY = window.scrollY;
|
|
741
|
+
if (this.vars.scrub) {
|
|
742
|
+
let progress = (scrollY - this.startScroll) / (this.endScroll - this.startScroll);
|
|
743
|
+
progress = Math.max(0, Math.min(1, progress));
|
|
744
|
+
const totalDuration = this.animation.duration + this.animation.delay;
|
|
745
|
+
this.animation.render(progress * totalDuration);
|
|
746
|
+
} else {
|
|
747
|
+
if (scrollY >= this.startScroll) {
|
|
748
|
+
if (!this.hasTriggered) {
|
|
749
|
+
this.hasTriggered = true;
|
|
750
|
+
this.animation.play();
|
|
751
|
+
if (this.vars.once) {
|
|
752
|
+
this.kill();
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
} else {
|
|
756
|
+
if (!this.vars.once && this.hasTriggered) {
|
|
757
|
+
this.hasTriggered = false;
|
|
758
|
+
this.animation.pause();
|
|
759
|
+
this.animation.render(0);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
kill() {
|
|
765
|
+
window.removeEventListener("scroll", this.onScroll);
|
|
766
|
+
window.removeEventListener("resize", this.refresh);
|
|
767
|
+
const idx = _ScrollTrigger.instances.indexOf(this);
|
|
768
|
+
if (idx !== -1) {
|
|
769
|
+
_ScrollTrigger.instances.splice(idx, 1);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
static killAll() {
|
|
773
|
+
const list = [..._ScrollTrigger.instances];
|
|
774
|
+
list.forEach((instance) => instance.kill());
|
|
775
|
+
_ScrollTrigger.instances = [];
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
// src/effects.ts
|
|
780
|
+
function slidingMenu(containerSelector, linksSelector, pillSelector, options = {}) {
|
|
781
|
+
const container = resolveTargets(containerSelector)[0];
|
|
782
|
+
const pill = resolveTargets(pillSelector)[0];
|
|
783
|
+
const links = container ? Array.from(container.querySelectorAll(linksSelector)) : [];
|
|
784
|
+
if (!container || !pill || links.length === 0) return;
|
|
785
|
+
const duration = options.duration !== void 0 ? options.duration : 0.35;
|
|
786
|
+
const ease = options.ease || "veryFast.out";
|
|
787
|
+
const movePill = (linkEl) => {
|
|
788
|
+
const rect = linkEl.getBoundingClientRect();
|
|
789
|
+
const parentRect = container.getBoundingClientRect();
|
|
790
|
+
const targetLeft = rect.left - parentRect.left;
|
|
791
|
+
const targetWidth = rect.width;
|
|
792
|
+
const targetTop = rect.top - parentRect.top;
|
|
793
|
+
const targetHeight = rect.height;
|
|
794
|
+
new Tween(pill, {
|
|
795
|
+
left: targetLeft,
|
|
796
|
+
width: targetWidth,
|
|
797
|
+
top: targetTop,
|
|
798
|
+
height: targetHeight,
|
|
799
|
+
opacity: 1,
|
|
800
|
+
duration,
|
|
801
|
+
ease,
|
|
802
|
+
autoPlay: true
|
|
803
|
+
});
|
|
804
|
+
};
|
|
805
|
+
links.forEach((link) => {
|
|
806
|
+
if (!(link instanceof HTMLElement)) return;
|
|
807
|
+
link.addEventListener("mouseenter", () => movePill(link), {
|
|
808
|
+
passive: true
|
|
809
|
+
});
|
|
810
|
+
});
|
|
811
|
+
container.addEventListener(
|
|
812
|
+
"mouseleave",
|
|
813
|
+
() => {
|
|
814
|
+
new Tween(pill, {
|
|
815
|
+
opacity: 0,
|
|
816
|
+
duration: 0.3,
|
|
817
|
+
ease: "medium.out",
|
|
818
|
+
autoPlay: true
|
|
819
|
+
});
|
|
820
|
+
},
|
|
821
|
+
{ passive: true }
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
function magnetic(target, options = {}) {
|
|
825
|
+
const resolved = resolveTargets(target);
|
|
826
|
+
const strength = options.strength !== void 0 ? options.strength : 0.45;
|
|
827
|
+
const proximity = options.proximity !== void 0 ? options.proximity : 100;
|
|
828
|
+
const duration = options.duration !== void 0 ? options.duration : 0.3;
|
|
829
|
+
const ease = options.ease || "veryFast.out";
|
|
830
|
+
resolved.forEach((el) => {
|
|
831
|
+
if (!(el instanceof HTMLElement)) return;
|
|
832
|
+
let isInside = false;
|
|
833
|
+
const onMouseMove = (e) => {
|
|
834
|
+
const rect = el.getBoundingClientRect();
|
|
835
|
+
const centerX = rect.left + rect.width / 2;
|
|
836
|
+
const centerY = rect.top + rect.height / 2;
|
|
837
|
+
const deltaX = e.clientX - centerX;
|
|
838
|
+
const deltaY = e.clientY - centerY;
|
|
839
|
+
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
840
|
+
if (distance < proximity) {
|
|
841
|
+
isInside = true;
|
|
842
|
+
new Tween(el, {
|
|
843
|
+
x: deltaX * strength,
|
|
844
|
+
y: deltaY * strength,
|
|
845
|
+
duration,
|
|
846
|
+
ease,
|
|
847
|
+
autoPlay: true
|
|
848
|
+
});
|
|
849
|
+
} else if (isInside) {
|
|
850
|
+
isInside = false;
|
|
851
|
+
new Tween(el, {
|
|
852
|
+
x: 0,
|
|
853
|
+
y: 0,
|
|
854
|
+
duration: 0.6,
|
|
855
|
+
ease: "medium.out",
|
|
856
|
+
autoPlay: true
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
window.addEventListener("mousemove", onMouseMove, { passive: true });
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
function tilt(target, options = {}) {
|
|
864
|
+
const resolved = resolveTargets(target);
|
|
865
|
+
const maxTilt = options.maxTilt !== void 0 ? options.maxTilt : 25;
|
|
866
|
+
const perspective = options.perspective !== void 0 ? options.perspective : 800;
|
|
867
|
+
const duration = options.duration !== void 0 ? options.duration : 0.2;
|
|
868
|
+
const ease = options.ease || "veryFast.out";
|
|
869
|
+
resolved.forEach((el) => {
|
|
870
|
+
if (!(el instanceof HTMLElement)) return;
|
|
871
|
+
const onMouseMove = (e) => {
|
|
872
|
+
const rect = el.getBoundingClientRect();
|
|
873
|
+
const mouseX = e.clientX - rect.left;
|
|
874
|
+
const mouseY = e.clientY - rect.top;
|
|
875
|
+
const pctX = mouseX / rect.width * 100;
|
|
876
|
+
const pctY = mouseY / rect.height * 100;
|
|
877
|
+
el.style.setProperty("--mouse-x", `${pctX}%`);
|
|
878
|
+
el.style.setProperty("--mouse-y", `${pctY}%`);
|
|
879
|
+
const tiltX = (mouseY / rect.height - 0.5) * -maxTilt;
|
|
880
|
+
const tiltY = (mouseX / rect.width - 0.5) * maxTilt;
|
|
881
|
+
new Tween(el, {
|
|
882
|
+
transform: `perspective(${perspective}px) rotateX(${tiltX}deg) rotateY(${tiltY}deg)`,
|
|
883
|
+
duration,
|
|
884
|
+
ease,
|
|
885
|
+
autoPlay: true
|
|
886
|
+
});
|
|
887
|
+
};
|
|
888
|
+
const onMouseLeave = () => {
|
|
889
|
+
new Tween(el, {
|
|
890
|
+
transform: `perspective(${perspective}px) rotateX(0deg) rotateY(0deg)`,
|
|
891
|
+
duration: 0.6,
|
|
892
|
+
ease: "medium.out",
|
|
893
|
+
autoPlay: true
|
|
894
|
+
});
|
|
895
|
+
el.style.setProperty("--mouse-x", "50%");
|
|
896
|
+
el.style.setProperty("--mouse-y", "50%");
|
|
897
|
+
};
|
|
898
|
+
el.addEventListener("mousemove", onMouseMove, { passive: true });
|
|
899
|
+
el.addEventListener("mouseleave", onMouseLeave, { passive: true });
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
function explodeOnScroll(target, options = {}) {
|
|
903
|
+
const resolved = resolveTargets(target);
|
|
904
|
+
const strength = options.strength !== void 0 ? options.strength : 1;
|
|
905
|
+
const start = options.start || "top 70%";
|
|
906
|
+
const end = options.end || "top 20%";
|
|
907
|
+
const ease = options.ease || "medium.out";
|
|
908
|
+
resolved.forEach((el) => {
|
|
909
|
+
const chars = splitText(el, { type: "chars" });
|
|
910
|
+
const tl = new Timeline({ paused: true });
|
|
911
|
+
chars.forEach((char) => {
|
|
912
|
+
const targetX = (Math.random() - 0.5) * 600 * strength;
|
|
913
|
+
const targetY = (Math.random() - 0.5) * 500 * strength;
|
|
914
|
+
const targetRot = (Math.random() - 0.5) * 360;
|
|
915
|
+
const targetScale = 0.1 + Math.random() * 2.2;
|
|
916
|
+
const tween = new Tween(char, {
|
|
917
|
+
x: targetX,
|
|
918
|
+
y: targetY,
|
|
919
|
+
rotation: targetRot,
|
|
920
|
+
scale: targetScale,
|
|
921
|
+
opacity: 0,
|
|
922
|
+
duration: 1,
|
|
923
|
+
ease,
|
|
924
|
+
autoPlay: false
|
|
925
|
+
});
|
|
926
|
+
tl.add(tween, 0);
|
|
927
|
+
});
|
|
928
|
+
new ScrollTrigger(tl, {
|
|
929
|
+
trigger: el,
|
|
930
|
+
start,
|
|
931
|
+
end,
|
|
932
|
+
scrub: true
|
|
933
|
+
});
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
function implodeOnScroll(target, options = {}) {
|
|
937
|
+
const resolved = resolveTargets(target);
|
|
938
|
+
const strength = options.strength !== void 0 ? options.strength : 1;
|
|
939
|
+
const start = options.start || "top 95%";
|
|
940
|
+
const end = options.end || "top 50%";
|
|
941
|
+
const ease = options.ease || "medium.out";
|
|
942
|
+
resolved.forEach((el) => {
|
|
943
|
+
const chars = splitText(el, { type: "chars" });
|
|
944
|
+
const tl = new Timeline({ paused: true });
|
|
945
|
+
chars.forEach((char) => {
|
|
946
|
+
const startX = (Math.random() - 0.5) * 700 * strength;
|
|
947
|
+
const startY = (Math.random() - 0.5) * 600 * strength;
|
|
948
|
+
const startRot = (Math.random() - 0.5) * 360;
|
|
949
|
+
const startScale = 0.1 + Math.random() * 2.5;
|
|
950
|
+
const tween = new Tween(
|
|
951
|
+
char,
|
|
952
|
+
{
|
|
953
|
+
x: 0,
|
|
954
|
+
y: 0,
|
|
955
|
+
rotation: 0,
|
|
956
|
+
scale: 1,
|
|
957
|
+
opacity: 1,
|
|
958
|
+
duration: 1,
|
|
959
|
+
ease,
|
|
960
|
+
autoPlay: false
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
x: startX,
|
|
964
|
+
y: startY,
|
|
965
|
+
rotation: startRot,
|
|
966
|
+
scale: startScale,
|
|
967
|
+
opacity: 0
|
|
968
|
+
}
|
|
969
|
+
);
|
|
970
|
+
tl.add(tween, 0);
|
|
971
|
+
});
|
|
972
|
+
new ScrollTrigger(tl, {
|
|
973
|
+
trigger: el,
|
|
974
|
+
start,
|
|
975
|
+
end,
|
|
976
|
+
scrub: true
|
|
977
|
+
});
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
function revealText(target, options = {}) {
|
|
981
|
+
const type = options.type || "chars";
|
|
982
|
+
const stagger = options.stagger !== void 0 ? options.stagger : type === "chars" ? 0.03 : 0.12;
|
|
983
|
+
const duration = options.duration !== void 0 ? options.duration : 0.8;
|
|
984
|
+
const ease = options.ease || "veryFast.out";
|
|
985
|
+
const delay = options.delay !== void 0 ? options.delay : 0;
|
|
986
|
+
const resolved = resolveTargets(target);
|
|
987
|
+
resolved.forEach((el) => {
|
|
988
|
+
const spans = splitText(el, { type });
|
|
989
|
+
const tl = new Timeline({ delay, paused: true });
|
|
990
|
+
spans.forEach((span, i) => {
|
|
991
|
+
const tween = new Tween(
|
|
992
|
+
span,
|
|
993
|
+
{
|
|
994
|
+
opacity: 1,
|
|
995
|
+
y: 0,
|
|
996
|
+
scale: 1,
|
|
997
|
+
rotation: 0,
|
|
998
|
+
duration,
|
|
999
|
+
ease,
|
|
1000
|
+
autoPlay: false
|
|
1001
|
+
},
|
|
1002
|
+
{
|
|
1003
|
+
opacity: 0,
|
|
1004
|
+
y: 40,
|
|
1005
|
+
scale: 0.5,
|
|
1006
|
+
rotation: 15
|
|
1007
|
+
}
|
|
1008
|
+
);
|
|
1009
|
+
tl.add(tween, i * stagger);
|
|
1010
|
+
});
|
|
1011
|
+
tl.play();
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
function scrollReveal(target, options = {}) {
|
|
1015
|
+
const resolved = resolveTargets(target);
|
|
1016
|
+
const stagger = options.stagger !== void 0 ? options.stagger : 0.1;
|
|
1017
|
+
const y = options.y !== void 0 ? options.y : 50;
|
|
1018
|
+
const duration = options.duration !== void 0 ? options.duration : 0.8;
|
|
1019
|
+
const ease = options.ease || "medium.out";
|
|
1020
|
+
const start = options.start || "top 85%";
|
|
1021
|
+
const once = options.once !== false;
|
|
1022
|
+
if (resolved.length === 0) return;
|
|
1023
|
+
const tl = new Timeline({ paused: true });
|
|
1024
|
+
resolved.forEach((el, i) => {
|
|
1025
|
+
const tween = new Tween(
|
|
1026
|
+
el,
|
|
1027
|
+
{
|
|
1028
|
+
opacity: 1,
|
|
1029
|
+
y: 0,
|
|
1030
|
+
duration,
|
|
1031
|
+
ease,
|
|
1032
|
+
autoPlay: false
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
opacity: 0,
|
|
1036
|
+
y
|
|
1037
|
+
}
|
|
1038
|
+
);
|
|
1039
|
+
tl.add(tween, i * stagger);
|
|
1040
|
+
});
|
|
1041
|
+
new ScrollTrigger(tl, {
|
|
1042
|
+
trigger: resolved[0],
|
|
1043
|
+
start,
|
|
1044
|
+
once
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
// src/index.ts
|
|
1049
|
+
var fluxo = {
|
|
1050
|
+
/**
|
|
1051
|
+
* Creates an animation that goes FROM the current values of the target
|
|
1052
|
+
* TO the values defined in 'vars'. Supports multiple targets, stagger, and scroll animator.
|
|
1053
|
+
*/
|
|
1054
|
+
to(target, vars) {
|
|
1055
|
+
const targets = resolveTargets(target);
|
|
1056
|
+
const hasScroll = vars.scroll !== void 0;
|
|
1057
|
+
const varsWithAutoPlay = { ...vars };
|
|
1058
|
+
if (hasScroll) {
|
|
1059
|
+
varsWithAutoPlay.autoPlay = false;
|
|
1060
|
+
}
|
|
1061
|
+
let animation;
|
|
1062
|
+
if (targets.length === 0) {
|
|
1063
|
+
animation = new Tween(null, varsWithAutoPlay);
|
|
1064
|
+
} else if (targets.length === 1) {
|
|
1065
|
+
animation = new Tween(targets[0], varsWithAutoPlay);
|
|
1066
|
+
} else {
|
|
1067
|
+
const tl = new Timeline({
|
|
1068
|
+
delay: varsWithAutoPlay.delay,
|
|
1069
|
+
onStart: varsWithAutoPlay.onStart,
|
|
1070
|
+
onUpdate: varsWithAutoPlay.onUpdate,
|
|
1071
|
+
onComplete: varsWithAutoPlay.onComplete,
|
|
1072
|
+
paused: true
|
|
1073
|
+
});
|
|
1074
|
+
const stagger = varsWithAutoPlay.stagger || 0;
|
|
1075
|
+
const tweenVars = { ...varsWithAutoPlay };
|
|
1076
|
+
delete tweenVars.delay;
|
|
1077
|
+
delete tweenVars.onStart;
|
|
1078
|
+
delete tweenVars.onUpdate;
|
|
1079
|
+
delete tweenVars.onComplete;
|
|
1080
|
+
delete tweenVars.stagger;
|
|
1081
|
+
delete tweenVars.scroll;
|
|
1082
|
+
targets.forEach((t, i) => {
|
|
1083
|
+
tl.to(t, tweenVars, i * stagger);
|
|
1084
|
+
});
|
|
1085
|
+
if (!hasScroll) {
|
|
1086
|
+
tl.play();
|
|
1087
|
+
}
|
|
1088
|
+
animation = tl;
|
|
1089
|
+
}
|
|
1090
|
+
if (hasScroll && vars.scroll) {
|
|
1091
|
+
new ScrollTrigger(animation, vars.scroll);
|
|
1092
|
+
}
|
|
1093
|
+
return animation;
|
|
1094
|
+
},
|
|
1095
|
+
/**
|
|
1096
|
+
* Creates an animation that goes FROM the values defined in 'vars'
|
|
1097
|
+
* TO the current values of the target. Supports multiple targets, stagger, and scroll animator.
|
|
1098
|
+
*/
|
|
1099
|
+
from(target, vars) {
|
|
1100
|
+
const targets = resolveTargets(target);
|
|
1101
|
+
const hasScroll = vars.scroll !== void 0;
|
|
1102
|
+
const varsWithAutoPlay = { ...vars };
|
|
1103
|
+
if (hasScroll) {
|
|
1104
|
+
varsWithAutoPlay.autoPlay = false;
|
|
1105
|
+
}
|
|
1106
|
+
let animation;
|
|
1107
|
+
if (targets.length === 0) {
|
|
1108
|
+
animation = new Tween(null, varsWithAutoPlay, void 0, true);
|
|
1109
|
+
} else if (targets.length === 1) {
|
|
1110
|
+
animation = new Tween(targets[0], varsWithAutoPlay, void 0, true);
|
|
1111
|
+
} else {
|
|
1112
|
+
const tl = new Timeline({
|
|
1113
|
+
delay: varsWithAutoPlay.delay,
|
|
1114
|
+
onStart: varsWithAutoPlay.onStart,
|
|
1115
|
+
onUpdate: varsWithAutoPlay.onUpdate,
|
|
1116
|
+
onComplete: varsWithAutoPlay.onComplete,
|
|
1117
|
+
paused: true
|
|
1118
|
+
});
|
|
1119
|
+
const stagger = varsWithAutoPlay.stagger || 0;
|
|
1120
|
+
const tweenVars = { ...varsWithAutoPlay };
|
|
1121
|
+
delete tweenVars.delay;
|
|
1122
|
+
delete tweenVars.onStart;
|
|
1123
|
+
delete tweenVars.onUpdate;
|
|
1124
|
+
delete tweenVars.onComplete;
|
|
1125
|
+
delete tweenVars.stagger;
|
|
1126
|
+
delete tweenVars.scroll;
|
|
1127
|
+
targets.forEach((t, i) => {
|
|
1128
|
+
tl.from(t, tweenVars, i * stagger);
|
|
1129
|
+
});
|
|
1130
|
+
if (!hasScroll) {
|
|
1131
|
+
tl.play();
|
|
1132
|
+
}
|
|
1133
|
+
animation = tl;
|
|
1134
|
+
}
|
|
1135
|
+
if (hasScroll && vars.scroll) {
|
|
1136
|
+
new ScrollTrigger(animation, vars.scroll);
|
|
1137
|
+
}
|
|
1138
|
+
return animation;
|
|
1139
|
+
},
|
|
1140
|
+
/**
|
|
1141
|
+
* Creates an animation that goes FROM the values defined in 'fromVars'
|
|
1142
|
+
* TO the values defined in 'toVars'. Supports multiple targets, stagger, and scroll animator.
|
|
1143
|
+
*/
|
|
1144
|
+
fromTo(target, fromVars, toVars) {
|
|
1145
|
+
const targets = resolveTargets(target);
|
|
1146
|
+
const hasScroll = toVars.scroll !== void 0;
|
|
1147
|
+
const toVarsWithAutoPlay = { ...toVars };
|
|
1148
|
+
if (hasScroll) {
|
|
1149
|
+
toVarsWithAutoPlay.autoPlay = false;
|
|
1150
|
+
}
|
|
1151
|
+
let animation;
|
|
1152
|
+
if (targets.length === 0) {
|
|
1153
|
+
animation = new Tween(null, toVarsWithAutoPlay, fromVars);
|
|
1154
|
+
} else if (targets.length === 1) {
|
|
1155
|
+
animation = new Tween(targets[0], toVarsWithAutoPlay, fromVars);
|
|
1156
|
+
} else {
|
|
1157
|
+
const tl = new Timeline({
|
|
1158
|
+
delay: toVarsWithAutoPlay.delay,
|
|
1159
|
+
onStart: toVarsWithAutoPlay.onStart,
|
|
1160
|
+
onUpdate: toVarsWithAutoPlay.onUpdate,
|
|
1161
|
+
onComplete: toVarsWithAutoPlay.onComplete,
|
|
1162
|
+
paused: true
|
|
1163
|
+
});
|
|
1164
|
+
const stagger = toVarsWithAutoPlay.stagger || 0;
|
|
1165
|
+
const tweenVars = { ...toVarsWithAutoPlay };
|
|
1166
|
+
delete tweenVars.delay;
|
|
1167
|
+
delete tweenVars.onStart;
|
|
1168
|
+
delete tweenVars.onUpdate;
|
|
1169
|
+
delete tweenVars.onComplete;
|
|
1170
|
+
delete tweenVars.stagger;
|
|
1171
|
+
delete tweenVars.scroll;
|
|
1172
|
+
targets.forEach((t, i) => {
|
|
1173
|
+
tl.fromTo(t, fromVars, tweenVars, i * stagger);
|
|
1174
|
+
});
|
|
1175
|
+
if (!hasScroll) {
|
|
1176
|
+
tl.play();
|
|
1177
|
+
}
|
|
1178
|
+
animation = tl;
|
|
1179
|
+
}
|
|
1180
|
+
if (hasScroll && toVars.scroll) {
|
|
1181
|
+
new ScrollTrigger(animation, toVars.scroll);
|
|
1182
|
+
}
|
|
1183
|
+
return animation;
|
|
1184
|
+
},
|
|
1185
|
+
/**
|
|
1186
|
+
* Creates a new Timeline instance for sequencing multiple animations.
|
|
1187
|
+
*/
|
|
1188
|
+
timeline(vars) {
|
|
1189
|
+
const hasScroll = vars?.scroll !== void 0;
|
|
1190
|
+
const timelineVars = { ...vars };
|
|
1191
|
+
if (hasScroll) {
|
|
1192
|
+
timelineVars.paused = true;
|
|
1193
|
+
}
|
|
1194
|
+
const tl = new Timeline(timelineVars);
|
|
1195
|
+
if (hasScroll && vars?.scroll) {
|
|
1196
|
+
new ScrollTrigger(tl, vars.scroll);
|
|
1197
|
+
}
|
|
1198
|
+
return tl;
|
|
1199
|
+
},
|
|
1200
|
+
/**
|
|
1201
|
+
* Splits text of DOM elements into individual character or word spans,
|
|
1202
|
+
* making them ready for cascaded stagger animations.
|
|
1203
|
+
*/
|
|
1204
|
+
splitText(target, options) {
|
|
1205
|
+
return splitText(target, options);
|
|
1206
|
+
},
|
|
1207
|
+
/**
|
|
1208
|
+
* Animates the outline drawing of SVG paths.
|
|
1209
|
+
*/
|
|
1210
|
+
drawSVG(target, vars) {
|
|
1211
|
+
const hasScroll = vars.scroll !== void 0;
|
|
1212
|
+
const varsWithAutoPlay = { ...vars };
|
|
1213
|
+
if (hasScroll) {
|
|
1214
|
+
varsWithAutoPlay.autoPlay = false;
|
|
1215
|
+
}
|
|
1216
|
+
const tween = drawSVG(target, varsWithAutoPlay);
|
|
1217
|
+
if (hasScroll && vars.scroll) {
|
|
1218
|
+
new ScrollTrigger(tween, vars.scroll);
|
|
1219
|
+
}
|
|
1220
|
+
return tween;
|
|
1221
|
+
},
|
|
1222
|
+
magnetic(target, options) {
|
|
1223
|
+
magnetic(target, options);
|
|
1224
|
+
},
|
|
1225
|
+
tilt(target, options) {
|
|
1226
|
+
tilt(target, options);
|
|
1227
|
+
},
|
|
1228
|
+
explodeOnScroll(target, options) {
|
|
1229
|
+
explodeOnScroll(target, options);
|
|
1230
|
+
},
|
|
1231
|
+
implodeOnScroll(target, options) {
|
|
1232
|
+
implodeOnScroll(target, options);
|
|
1233
|
+
},
|
|
1234
|
+
revealText(target, options) {
|
|
1235
|
+
revealText(target, options);
|
|
1236
|
+
},
|
|
1237
|
+
scrollReveal(target, options) {
|
|
1238
|
+
scrollReveal(target, options);
|
|
1239
|
+
},
|
|
1240
|
+
slidingMenu(container, links, pill, options) {
|
|
1241
|
+
slidingMenu(container, links, pill, options);
|
|
1242
|
+
},
|
|
1243
|
+
killAllTriggers() {
|
|
1244
|
+
ScrollTrigger.killAll();
|
|
1245
|
+
}
|
|
1246
|
+
};
|
|
1247
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1248
|
+
0 && (module.exports = {
|
|
1249
|
+
ScrollTrigger,
|
|
1250
|
+
Timeline,
|
|
1251
|
+
Tween,
|
|
1252
|
+
drawSVG,
|
|
1253
|
+
easings,
|
|
1254
|
+
explodeOnScroll,
|
|
1255
|
+
fluxo,
|
|
1256
|
+
implodeOnScroll,
|
|
1257
|
+
magnetic,
|
|
1258
|
+
resolveTargets,
|
|
1259
|
+
revealText,
|
|
1260
|
+
scrollReveal,
|
|
1261
|
+
slidingMenu,
|
|
1262
|
+
splitText,
|
|
1263
|
+
ticker,
|
|
1264
|
+
tilt
|
|
1265
|
+
});
|