@sarmal/core 0.9.1 → 0.9.10
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/dist/auto-init.cjs +196 -157
- package/dist/auto-init.cjs.map +1 -1
- package/dist/auto-init.d.cts +2 -1
- package/dist/auto-init.d.ts +2 -1
- package/dist/auto-init.js +195 -156
- package/dist/auto-init.js.map +1 -1
- package/dist/curves/artemis2.cjs +7 -10
- package/dist/curves/artemis2.d.cts +1 -1
- package/dist/curves/artemis2.d.ts +1 -1
- package/dist/curves/artemis2.js +6 -9
- package/dist/curves/astroid.cjs +4 -4
- package/dist/curves/astroid.d.cts +1 -1
- package/dist/curves/astroid.d.ts +1 -1
- package/dist/curves/astroid.js +3 -3
- package/dist/curves/deltoid.cjs +4 -4
- package/dist/curves/deltoid.d.cts +1 -1
- package/dist/curves/deltoid.d.ts +1 -1
- package/dist/curves/deltoid.js +3 -3
- package/dist/curves/epicycloid3.cjs +4 -4
- package/dist/curves/epicycloid3.d.cts +1 -1
- package/dist/curves/epicycloid3.d.ts +1 -1
- package/dist/curves/epicycloid3.js +3 -3
- package/dist/curves/epitrochoid7.cjs +5 -5
- package/dist/curves/epitrochoid7.d.cts +1 -1
- package/dist/curves/epitrochoid7.d.ts +1 -1
- package/dist/curves/epitrochoid7.js +4 -4
- package/dist/curves/index.cjs +28 -32
- package/dist/curves/index.d.cts +11 -11
- package/dist/curves/index.d.ts +11 -11
- package/dist/curves/index.js +28 -44
- package/dist/curves/lame.cjs +5 -6
- package/dist/curves/lame.d.cts +1 -1
- package/dist/curves/lame.d.ts +1 -1
- package/dist/curves/lame.js +4 -5
- package/dist/curves/lissajous32.cjs +4 -4
- package/dist/curves/lissajous32.d.cts +1 -1
- package/dist/curves/lissajous32.d.ts +1 -1
- package/dist/curves/lissajous32.js +3 -3
- package/dist/curves/lissajous43.cjs +4 -4
- package/dist/curves/lissajous43.d.cts +1 -1
- package/dist/curves/lissajous43.d.ts +1 -1
- package/dist/curves/lissajous43.js +3 -3
- package/dist/curves/rose3.cjs +4 -4
- package/dist/curves/rose3.d.cts +1 -1
- package/dist/curves/rose3.d.ts +1 -1
- package/dist/curves/rose3.js +3 -3
- package/dist/curves/rose5.cjs +4 -4
- package/dist/curves/rose5.d.cts +1 -1
- package/dist/curves/rose5.d.ts +1 -1
- package/dist/curves/rose5.js +3 -3
- package/dist/index.cjs +233 -265
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -64
- package/dist/index.d.ts +31 -64
- package/dist/index.js +233 -282
- package/dist/index.js.map +1 -1
- package/dist/types-cR2xOewv.d.cts +223 -0
- package/dist/types-cR2xOewv.d.ts +223 -0
- package/package.json +5 -3
- package/dist/types-DX8VfIVK.d.cts +0 -226
- package/dist/types-DX8VfIVK.d.ts +0 -226
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/engine.ts
|
|
4
4
|
var TWO_PI = Math.PI * 2;
|
|
5
5
|
var POINTS_PER_PERIOD_UNIT = 50;
|
|
6
|
+
function lerp(start, end, t) {
|
|
7
|
+
return start + (end - start) * t;
|
|
8
|
+
}
|
|
9
|
+
var EMPTY_PARAMS = {};
|
|
6
10
|
var CircularBuffer = class {
|
|
7
11
|
constructor(capacity) {
|
|
8
12
|
this.head = 0;
|
|
@@ -45,16 +49,29 @@ var CircularBuffer = class {
|
|
|
45
49
|
}
|
|
46
50
|
};
|
|
47
51
|
function resolveCurve(curveDef) {
|
|
52
|
+
const period = curveDef.period ?? TWO_PI;
|
|
53
|
+
if (!Number.isFinite(period) || period <= 0) {
|
|
54
|
+
throw new RangeError(`[sarmal] period must be a positive finite number, got ${period}`);
|
|
55
|
+
}
|
|
56
|
+
const speed = curveDef.speed ?? 1;
|
|
57
|
+
if (!Number.isFinite(speed)) {
|
|
58
|
+
throw new RangeError(`[sarmal] speed must be a finite number, got ${speed}`);
|
|
59
|
+
}
|
|
48
60
|
return {
|
|
49
61
|
name: curveDef.name,
|
|
50
62
|
fn: curveDef.fn,
|
|
51
|
-
period
|
|
52
|
-
speed
|
|
63
|
+
period,
|
|
64
|
+
speed,
|
|
53
65
|
skeleton: curveDef.skeleton,
|
|
54
|
-
skeletonFn: curveDef.skeletonFn
|
|
66
|
+
skeletonFn: curveDef.skeletonFn
|
|
55
67
|
};
|
|
56
68
|
}
|
|
57
69
|
function createEngine(curveDef, trailLength = 120) {
|
|
70
|
+
if (!Number.isFinite(trailLength) || trailLength <= 0) {
|
|
71
|
+
throw new RangeError(
|
|
72
|
+
`[sarmal] trailLength must be a positive finite number, got ${trailLength}`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
58
75
|
let curve = resolveCurve(curveDef);
|
|
59
76
|
const trail = new CircularBuffer(trailLength);
|
|
60
77
|
let t = 0;
|
|
@@ -67,21 +84,25 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
67
84
|
return c.skeletonFn(sampleT);
|
|
68
85
|
}
|
|
69
86
|
if (c.skeleton === "live") {
|
|
70
|
-
return c.fn(sampleT, actualTime,
|
|
87
|
+
return c.fn(sampleT, actualTime, EMPTY_PARAMS);
|
|
71
88
|
}
|
|
72
|
-
return c.fn(sampleT, 0,
|
|
89
|
+
return c.fn(sampleT, 0, EMPTY_PARAMS);
|
|
73
90
|
}
|
|
74
91
|
return {
|
|
75
92
|
tick(deltaTime) {
|
|
76
|
-
|
|
93
|
+
let effectiveSpeed = curve.speed;
|
|
94
|
+
if (morphCurveB !== null && _morphAlpha !== null) {
|
|
95
|
+
effectiveSpeed = lerp(curve.speed, morphCurveB.speed, _morphAlpha);
|
|
96
|
+
}
|
|
97
|
+
t = (t + effectiveSpeed * deltaTime) % curve.period;
|
|
77
98
|
actualTime += deltaTime;
|
|
78
99
|
if (morphCurveB !== null && _morphAlpha !== null) {
|
|
79
|
-
const a = curve.fn(t, actualTime,
|
|
80
|
-
const tB = _morphStrategy === "normalized" ?
|
|
81
|
-
const b = morphCurveB.fn(tB, actualTime,
|
|
100
|
+
const a = curve.fn(t, actualTime, EMPTY_PARAMS);
|
|
101
|
+
const tB = _morphStrategy === "normalized" ? t / curve.period * morphCurveB.period : t;
|
|
102
|
+
const b = morphCurveB.fn(tB, actualTime, EMPTY_PARAMS);
|
|
82
103
|
trail.push(a.x + (b.x - a.x) * _morphAlpha, a.y + (b.y - a.y) * _morphAlpha);
|
|
83
104
|
} else {
|
|
84
|
-
const point = curve.fn(t, actualTime,
|
|
105
|
+
const point = curve.fn(t, actualTime, EMPTY_PARAMS);
|
|
85
106
|
trail.push(point.x, point.y);
|
|
86
107
|
}
|
|
87
108
|
return trail.toArray();
|
|
@@ -101,14 +122,14 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
101
122
|
trail.clear();
|
|
102
123
|
},
|
|
103
124
|
seek(newT, { clearTrail = false } = {}) {
|
|
104
|
-
t = (
|
|
125
|
+
t = (newT % curve.period + curve.period) % curve.period;
|
|
105
126
|
if (clearTrail) {
|
|
106
127
|
trail.clear();
|
|
107
128
|
}
|
|
108
129
|
},
|
|
109
130
|
seekWithTrail(targetT, { wrap = false, step = curve.period / trailLength } = {}) {
|
|
110
131
|
const advance = curve.speed * step;
|
|
111
|
-
const target = (
|
|
132
|
+
const target = (targetT % curve.period + curve.period) % curve.period;
|
|
112
133
|
const targetTime = target / curve.speed;
|
|
113
134
|
t = target;
|
|
114
135
|
actualTime = targetTime;
|
|
@@ -117,9 +138,9 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
117
138
|
const count = wrap ? trailLength : Math.min(trailLength, pointsFromStart);
|
|
118
139
|
for (let i = count - 1; i >= 0; i--) {
|
|
119
140
|
const sampleT = target - i * advance;
|
|
120
|
-
const wrappedT = sampleT
|
|
141
|
+
const wrappedT = (sampleT % curve.period + curve.period) % curve.period;
|
|
121
142
|
const time = targetTime - i * step;
|
|
122
|
-
const point = curve.fn(wrappedT, time,
|
|
143
|
+
const point = curve.fn(wrappedT, time, EMPTY_PARAMS);
|
|
123
144
|
trail.push(point.x, point.y);
|
|
124
145
|
}
|
|
125
146
|
},
|
|
@@ -134,16 +155,13 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
134
155
|
...frozenB,
|
|
135
156
|
fn: (sampleT, time, params) => {
|
|
136
157
|
const a = frozenA.fn(sampleT, time, params);
|
|
137
|
-
const tB =
|
|
138
|
-
frozenStrategy === "normalized"
|
|
139
|
-
? (sampleT / frozenA.period) * frozenB.period
|
|
140
|
-
: sampleT;
|
|
158
|
+
const tB = frozenStrategy === "normalized" ? sampleT / frozenA.period * frozenB.period : sampleT;
|
|
141
159
|
const b = frozenB.fn(tB, time, params);
|
|
142
160
|
return {
|
|
143
161
|
x: a.x + (b.x - a.x) * frozenAlpha,
|
|
144
|
-
y: a.y + (b.y - a.y) * frozenAlpha
|
|
162
|
+
y: a.y + (b.y - a.y) * frozenAlpha
|
|
145
163
|
};
|
|
146
|
-
}
|
|
164
|
+
}
|
|
147
165
|
};
|
|
148
166
|
}
|
|
149
167
|
_morphStrategy = strategy;
|
|
@@ -156,7 +174,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
156
174
|
completeMorph() {
|
|
157
175
|
if (morphCurveB !== null) {
|
|
158
176
|
if (_morphStrategy === "normalized" && curve.period !== morphCurveB.period) {
|
|
159
|
-
t =
|
|
177
|
+
t = t / curve.period * morphCurveB.period;
|
|
160
178
|
}
|
|
161
179
|
curve = morphCurveB;
|
|
162
180
|
}
|
|
@@ -168,46 +186,132 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
168
186
|
const points = new Array(steps);
|
|
169
187
|
if (morphCurveB !== null && _morphAlpha !== null) {
|
|
170
188
|
for (let i = 0; i < steps; i++) {
|
|
171
|
-
const sampleT =
|
|
189
|
+
const sampleT = i / (steps - 1) * curve.period;
|
|
172
190
|
const a = sampleSkeleton(curve, sampleT);
|
|
173
|
-
const tB =
|
|
174
|
-
_morphStrategy === "normalized"
|
|
175
|
-
? (sampleT / curve.period) * morphCurveB.period
|
|
176
|
-
: sampleT;
|
|
191
|
+
const tB = _morphStrategy === "normalized" ? sampleT / curve.period * morphCurveB.period : sampleT;
|
|
177
192
|
const b = sampleSkeleton(morphCurveB, tB);
|
|
178
193
|
points[i] = {
|
|
179
194
|
x: a.x + (b.x - a.x) * _morphAlpha,
|
|
180
|
-
y: a.y + (b.y - a.y) * _morphAlpha
|
|
195
|
+
y: a.y + (b.y - a.y) * _morphAlpha
|
|
181
196
|
};
|
|
182
197
|
}
|
|
183
198
|
return points;
|
|
184
199
|
}
|
|
185
200
|
for (let i = 0; i < steps; i++) {
|
|
186
|
-
const sampleT =
|
|
201
|
+
const sampleT = i / (steps - 1) * curve.period;
|
|
187
202
|
points[i] = sampleSkeleton(curve, sampleT);
|
|
188
203
|
}
|
|
189
204
|
return points;
|
|
190
|
-
}
|
|
205
|
+
}
|
|
191
206
|
};
|
|
192
207
|
}
|
|
193
208
|
|
|
194
|
-
// src/renderer.ts
|
|
209
|
+
// src/renderer-shared.ts
|
|
195
210
|
var DEFAULT_MORPH_DURATION_MS = 300;
|
|
196
|
-
var DEFAULT_HEAD_RADIUS = 4;
|
|
197
|
-
var DEFAULT_SKELETON_COLOR = "#ffffff";
|
|
198
211
|
var DEFAULT_SKELETON_OPACITY = 0.15;
|
|
199
212
|
var FIT_PADDING = 0.1;
|
|
200
213
|
var TRAIL_FADE_CURVE = 1.5;
|
|
201
214
|
var TRAIL_MAX_OPACITY = 0.88;
|
|
202
215
|
var TRAIL_MIN_WIDTH = 0.5;
|
|
203
216
|
var TRAIL_MAX_WIDTH = 2.5;
|
|
217
|
+
function computeTangent(trail, i) {
|
|
218
|
+
const count = trail.length;
|
|
219
|
+
if (count < 2) {
|
|
220
|
+
return { x: 1, y: 0 };
|
|
221
|
+
}
|
|
222
|
+
if (i === 0) {
|
|
223
|
+
const dx2 = trail[1].x - trail[0].x;
|
|
224
|
+
const dy2 = trail[1].y - trail[0].y;
|
|
225
|
+
const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
|
|
226
|
+
return { x: dx2 / len2, y: dy2 / len2 };
|
|
227
|
+
}
|
|
228
|
+
if (i === count - 1) {
|
|
229
|
+
const dx2 = trail[count - 1].x - trail[count - 2].x;
|
|
230
|
+
const dy2 = trail[count - 1].y - trail[count - 2].y;
|
|
231
|
+
const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
|
|
232
|
+
return { x: dx2 / len2, y: dy2 / len2 };
|
|
233
|
+
}
|
|
234
|
+
const dx = trail[i + 1].x - trail[i - 1].x;
|
|
235
|
+
const dy = trail[i + 1].y - trail[i - 1].y;
|
|
236
|
+
const len = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
237
|
+
return { x: dx / len, y: dy / len };
|
|
238
|
+
}
|
|
239
|
+
function computeNormal(trail, i) {
|
|
240
|
+
const tangent = computeTangent(trail, i);
|
|
241
|
+
return { x: -tangent.y, y: tangent.x };
|
|
242
|
+
}
|
|
243
|
+
function computeTrailQuad(trail, i, trailCount, toX, toY) {
|
|
244
|
+
const progress = i / (trailCount - 1);
|
|
245
|
+
const nextProgress = (i + 1) / (trailCount - 1);
|
|
246
|
+
const opacity = Math.pow(progress, TRAIL_FADE_CURVE) * TRAIL_MAX_OPACITY;
|
|
247
|
+
const w0 = (TRAIL_MIN_WIDTH + progress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH)) / 2;
|
|
248
|
+
const w1 = (TRAIL_MIN_WIDTH + nextProgress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH)) / 2;
|
|
249
|
+
const curr = trail[i];
|
|
250
|
+
const next = trail[i + 1];
|
|
251
|
+
const n0 = computeNormal(trail, i);
|
|
252
|
+
const n1 = computeNormal(trail, i + 1);
|
|
253
|
+
const cx = toX(curr);
|
|
254
|
+
const cy = toY(curr);
|
|
255
|
+
const nx = toX(next);
|
|
256
|
+
const ny = toY(next);
|
|
257
|
+
return {
|
|
258
|
+
l0x: cx + n0.x * w0,
|
|
259
|
+
l0y: cy + n0.y * w0,
|
|
260
|
+
r0x: cx - n0.x * w0,
|
|
261
|
+
r0y: cy - n0.y * w0,
|
|
262
|
+
l1x: nx + n1.x * w1,
|
|
263
|
+
l1y: ny + n1.y * w1,
|
|
264
|
+
r1x: nx - n1.x * w1,
|
|
265
|
+
r1y: ny - n1.y * w1,
|
|
266
|
+
opacity,
|
|
267
|
+
progress
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function computeBoundaries(pts, logicalWidth, logicalHeight) {
|
|
271
|
+
if (pts.length === 0) return null;
|
|
272
|
+
const first = pts[0];
|
|
273
|
+
let minX = first.x, maxX = first.x, minY = first.y, maxY = first.y;
|
|
274
|
+
for (const p of pts) {
|
|
275
|
+
if (p.x < minX) {
|
|
276
|
+
minX = p.x;
|
|
277
|
+
}
|
|
278
|
+
if (p.x > maxX) {
|
|
279
|
+
maxX = p.x;
|
|
280
|
+
}
|
|
281
|
+
if (p.y < minY) {
|
|
282
|
+
minY = p.y;
|
|
283
|
+
}
|
|
284
|
+
if (p.y > maxY) {
|
|
285
|
+
maxY = p.y;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const w = maxX - minX;
|
|
289
|
+
const h = maxY - minY;
|
|
290
|
+
if (w === 0 && h === 0) {
|
|
291
|
+
throw new Error(
|
|
292
|
+
"[sarmal] Degenerate curve: all skeleton points are identical. Check that your curve fn returns distinct points for different values of t."
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
const scaleX = logicalWidth / (w * (1 + FIT_PADDING * 2));
|
|
296
|
+
const scaleY = logicalHeight / (h * (1 + FIT_PADDING * 2));
|
|
297
|
+
const scale = Math.min(scaleX, scaleY);
|
|
298
|
+
return {
|
|
299
|
+
scale,
|
|
300
|
+
offsetX: (logicalWidth - w * scale) / 2 - minX * scale,
|
|
301
|
+
offsetY: (logicalHeight - h * scale) / 2 - minY * scale
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// src/renderer.ts
|
|
306
|
+
var DEFAULT_HEAD_RADIUS = 4;
|
|
307
|
+
var DEFAULT_SKELETON_COLOR = "#ffffff";
|
|
204
308
|
var GRADIENT = {
|
|
205
309
|
bard: ["#a855f7", "#3b82f6", "#14b8a6", "#ec4899"],
|
|
206
310
|
sunset: ["#f97316", "#dc2626", "#9333ea", "#f472b6"],
|
|
207
311
|
ocean: ["#1e3a8a", "#06b6d4", "#22d3ee", "#e0f2fe"],
|
|
208
312
|
ice: ["#1e3a8a", "#67e8f9"],
|
|
209
313
|
fire: ["#7f1d1d", "#fbbf24"],
|
|
210
|
-
forest: ["#14532d", "#86efac"]
|
|
314
|
+
forest: ["#14532d", "#86efac"]
|
|
211
315
|
};
|
|
212
316
|
var PRESETS = {
|
|
213
317
|
bard: GRADIENT.bard,
|
|
@@ -215,16 +319,16 @@ var PRESETS = {
|
|
|
215
319
|
ocean: GRADIENT.ocean,
|
|
216
320
|
ice: GRADIENT.ice,
|
|
217
321
|
fire: GRADIENT.fire,
|
|
218
|
-
forest: GRADIENT.forest
|
|
322
|
+
forest: GRADIENT.forest
|
|
219
323
|
};
|
|
220
324
|
function hexToRgb(hex) {
|
|
221
325
|
const n = parseInt(hex.slice(1), 16);
|
|
222
|
-
return { r: n >> 16, g:
|
|
326
|
+
return { r: n >> 16, g: n >> 8 & 255, b: n & 255 };
|
|
223
327
|
}
|
|
224
328
|
var lerpRgb = (a, b, t) => ({
|
|
225
329
|
r: Math.round(a.r + (b.r - a.r) * t),
|
|
226
330
|
g: Math.round(a.g + (b.g - a.g) * t),
|
|
227
|
-
b: Math.round(a.b + (b.b - a.b) * t)
|
|
331
|
+
b: Math.round(a.b + (b.b - a.b) * t)
|
|
228
332
|
});
|
|
229
333
|
function getPaletteColor(palette, position, timeOffset = 0) {
|
|
230
334
|
if (palette.length === 0) return { r: 255, g: 255, b: 255 };
|
|
@@ -244,33 +348,7 @@ function resolvePalette(palette, trailStyle) {
|
|
|
244
348
|
}
|
|
245
349
|
function hexToRgbComponents(hex) {
|
|
246
350
|
const n = parseInt(hex.slice(1), 16);
|
|
247
|
-
return `${n >> 16},${
|
|
248
|
-
}
|
|
249
|
-
function computeTangent(trail, i) {
|
|
250
|
-
const count = trail.length;
|
|
251
|
-
if (count < 2) {
|
|
252
|
-
return { x: 1, y: 0 };
|
|
253
|
-
}
|
|
254
|
-
if (i === 0) {
|
|
255
|
-
const dx2 = trail[1].x - trail[0].x;
|
|
256
|
-
const dy2 = trail[1].y - trail[0].y;
|
|
257
|
-
const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
|
|
258
|
-
return { x: dx2 / len2, y: dy2 / len2 };
|
|
259
|
-
}
|
|
260
|
-
if (i === count - 1) {
|
|
261
|
-
const dx2 = trail[count - 1].x - trail[count - 2].x;
|
|
262
|
-
const dy2 = trail[count - 1].y - trail[count - 2].y;
|
|
263
|
-
const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
|
|
264
|
-
return { x: dx2 / len2, y: dy2 / len2 };
|
|
265
|
-
}
|
|
266
|
-
const dx = trail[i + 1].x - trail[i - 1].x;
|
|
267
|
-
const dy = trail[i + 1].y - trail[i - 1].y;
|
|
268
|
-
const len = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
269
|
-
return { x: dx / len, y: dy / len };
|
|
270
|
-
}
|
|
271
|
-
function computeNormal(trail, i) {
|
|
272
|
-
const tangent = computeTangent(trail, i);
|
|
273
|
-
return { x: -tangent.y, y: tangent.x };
|
|
351
|
+
return `${n >> 16},${n >> 8 & 255},${n & 255}`;
|
|
274
352
|
}
|
|
275
353
|
function applyDprSizing(target, logicalWidth, logicalHeight, dpr) {
|
|
276
354
|
target.style.width = `${logicalWidth}px`;
|
|
@@ -289,7 +367,7 @@ function createRenderer(options) {
|
|
|
289
367
|
skeletonColor: options.skeletonColor ?? DEFAULT_SKELETON_COLOR,
|
|
290
368
|
trailColor: options.trailColor ?? "#ffffff",
|
|
291
369
|
headColor: options.headColor ?? "#ffffff",
|
|
292
|
-
headRadius: options.headRadius ?? DEFAULT_HEAD_RADIUS
|
|
370
|
+
headRadius: options.headRadius ?? DEFAULT_HEAD_RADIUS
|
|
293
371
|
};
|
|
294
372
|
const trailStyle = options.trailStyle ?? "default";
|
|
295
373
|
const palette = resolvePalette(options.palette, trailStyle);
|
|
@@ -319,34 +397,8 @@ function createRenderer(options) {
|
|
|
319
397
|
let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
|
|
320
398
|
let morphAlpha = 0;
|
|
321
399
|
let gradientAnimTime = 0;
|
|
322
|
-
function computeBoundaries(pts) {
|
|
323
|
-
if (pts.length === 0) return null;
|
|
324
|
-
const first = pts[0];
|
|
325
|
-
let minX = first.x,
|
|
326
|
-
maxX = first.x,
|
|
327
|
-
minY = first.y,
|
|
328
|
-
maxY = first.y;
|
|
329
|
-
for (const p of pts) {
|
|
330
|
-
if (p.x < minX) minX = p.x;
|
|
331
|
-
if (p.x > maxX) maxX = p.x;
|
|
332
|
-
if (p.y < minY) minY = p.y;
|
|
333
|
-
if (p.y > maxY) maxY = p.y;
|
|
334
|
-
}
|
|
335
|
-
const width = maxX - minX;
|
|
336
|
-
const height = maxY - minY;
|
|
337
|
-
const scaleX = logicalWidth / (width * (1 + FIT_PADDING * 2));
|
|
338
|
-
const scaleY = logicalHeight / (height * (1 + FIT_PADDING * 2));
|
|
339
|
-
const s = Math.min(scaleX, scaleY);
|
|
340
|
-
const boundsWidth = width * s;
|
|
341
|
-
const boundsHeight = height * s;
|
|
342
|
-
return {
|
|
343
|
-
scale: s,
|
|
344
|
-
offsetX: (logicalWidth - boundsWidth) / 2 - minX * s,
|
|
345
|
-
offsetY: (logicalHeight - boundsHeight) / 2 - minY * s,
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
400
|
function calculateBoundaries() {
|
|
349
|
-
const b = computeBoundaries(skeleton);
|
|
401
|
+
const b = computeBoundaries(skeleton, logicalWidth, logicalHeight);
|
|
350
402
|
if (b) {
|
|
351
403
|
scale = b.scale;
|
|
352
404
|
offsetX = b.offsetX;
|
|
@@ -410,32 +462,22 @@ function createRenderer(options) {
|
|
|
410
462
|
if (trailCount < 2) {
|
|
411
463
|
return;
|
|
412
464
|
}
|
|
465
|
+
const toX = (p) => p.x * scale + offsetX;
|
|
466
|
+
const toY = (p) => p.y * scale + offsetY;
|
|
413
467
|
for (let i = 0; i < trailCount - 1; i++) {
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
const n0 = computeNormal(trail, i);
|
|
422
|
-
const n1 = computeNormal(trail, i + 1);
|
|
423
|
-
const halfW0 = width / 2;
|
|
424
|
-
const halfW1 = nextWidth / 2;
|
|
425
|
-
const l0x = curr.x * scale + offsetX + n0.x * halfW0;
|
|
426
|
-
const l0y = curr.y * scale + offsetY + n0.y * halfW0;
|
|
427
|
-
const r0x = curr.x * scale + offsetX - n0.x * halfW0;
|
|
428
|
-
const r0y = curr.y * scale + offsetY - n0.y * halfW0;
|
|
429
|
-
const l1x = next.x * scale + offsetX + n1.x * halfW1;
|
|
430
|
-
const l1y = next.y * scale + offsetY + n1.y * halfW1;
|
|
431
|
-
const r1x = next.x * scale + offsetX - n1.x * halfW1;
|
|
432
|
-
const r1y = next.y * scale + offsetY - n1.y * halfW1;
|
|
468
|
+
const { l0x, l0y, r0x, r0y, l1x, l1y, r1x, r1y, opacity, progress } = computeTrailQuad(
|
|
469
|
+
trail,
|
|
470
|
+
i,
|
|
471
|
+
trailCount,
|
|
472
|
+
toX,
|
|
473
|
+
toY
|
|
474
|
+
);
|
|
433
475
|
if (trailStyle === "default") {
|
|
434
|
-
ctx.fillStyle = `rgba(${trailRgb},${
|
|
476
|
+
ctx.fillStyle = `rgba(${trailRgb},${opacity})`;
|
|
435
477
|
} else {
|
|
436
478
|
const timeOffset = trailStyle === "gradient-animated" ? gradientAnimTime * 5e-4 : 0;
|
|
437
479
|
const color = getPaletteColor(palette, progress, timeOffset);
|
|
438
|
-
ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${
|
|
480
|
+
ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${opacity})`;
|
|
439
481
|
}
|
|
440
482
|
ctx.beginPath();
|
|
441
483
|
ctx.moveTo(l0x, l0y);
|
|
@@ -468,7 +510,7 @@ function createRenderer(options) {
|
|
|
468
510
|
morphAlpha = Math.min(1, morphAlpha + deltaTime / (morphDurationMs / 1e3));
|
|
469
511
|
engine.setMorphAlpha(morphAlpha);
|
|
470
512
|
const interpolatedSkeleton = engine.getSarmalSkeleton();
|
|
471
|
-
const bounds = computeBoundaries(interpolatedSkeleton);
|
|
513
|
+
const bounds = computeBoundaries(interpolatedSkeleton, logicalWidth, logicalHeight);
|
|
472
514
|
if (bounds) {
|
|
473
515
|
scale = bounds.scale;
|
|
474
516
|
offsetX = bounds.offsetX;
|
|
@@ -548,19 +590,33 @@ function createRenderer(options) {
|
|
|
548
590
|
return new Promise((resolve) => {
|
|
549
591
|
morphResolve = resolve;
|
|
550
592
|
});
|
|
551
|
-
}
|
|
593
|
+
}
|
|
552
594
|
};
|
|
553
595
|
}
|
|
554
596
|
|
|
555
597
|
// src/renderer-svg.ts
|
|
556
|
-
var DEFAULT_MORPH_DURATION_MS2 = 300;
|
|
557
598
|
var MAX_TRAIL_SEGMENTS = 200;
|
|
558
|
-
var
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
599
|
+
var EMPTY_PARAMS2 = {};
|
|
600
|
+
function pointsToPathString(pts, scale, offsetX, offsetY) {
|
|
601
|
+
if (pts.length < 2) return "";
|
|
602
|
+
const px = (p) => (p.x * scale + offsetX).toFixed(2);
|
|
603
|
+
const py = (p) => (p.y * scale + offsetY).toFixed(2);
|
|
604
|
+
let d = `M${px(pts[0])} ${py(pts[0])}`;
|
|
605
|
+
for (let i = 1; i < pts.length; i++) {
|
|
606
|
+
d += ` L${px(pts[i])} ${py(pts[i])}`;
|
|
607
|
+
}
|
|
608
|
+
return d + " Z";
|
|
609
|
+
}
|
|
610
|
+
function sampleCurveSkeleton(curveDef) {
|
|
611
|
+
const period = curveDef.period ?? Math.PI * 2;
|
|
612
|
+
const samples = Math.ceil(period * 50);
|
|
613
|
+
const pts = Array.from({ length: samples });
|
|
614
|
+
for (let i = 0; i < samples; i++) {
|
|
615
|
+
const t = i / (samples - 1) * period;
|
|
616
|
+
pts[i] = curveDef.skeletonFn ? curveDef.skeletonFn(t) : curveDef.fn(t, 0, EMPTY_PARAMS2);
|
|
617
|
+
}
|
|
618
|
+
return pts;
|
|
619
|
+
}
|
|
564
620
|
function el(tag) {
|
|
565
621
|
return document.createElementNS("http://www.w3.org/2000/svg", tag);
|
|
566
622
|
}
|
|
@@ -571,7 +627,7 @@ function createSVGRenderer(options) {
|
|
|
571
627
|
trailColor: options.trailColor ?? "#ffffff",
|
|
572
628
|
headColor: options.headColor ?? "#ffffff",
|
|
573
629
|
headRadius: options.headRadius ?? 4,
|
|
574
|
-
ariaLabel: options.ariaLabel ?? "Loading"
|
|
630
|
+
ariaLabel: options.ariaLabel ?? "Loading"
|
|
575
631
|
};
|
|
576
632
|
const rect = container.getBoundingClientRect();
|
|
577
633
|
const width = rect.width || 200;
|
|
@@ -588,7 +644,7 @@ function createSVGRenderer(options) {
|
|
|
588
644
|
const skeletonPath = el("path");
|
|
589
645
|
skeletonPath.setAttribute("fill", "none");
|
|
590
646
|
skeletonPath.setAttribute("stroke", opts.skeletonColor);
|
|
591
|
-
skeletonPath.setAttribute("stroke-opacity", String(
|
|
647
|
+
skeletonPath.setAttribute("stroke-opacity", String(DEFAULT_SKELETON_OPACITY));
|
|
592
648
|
skeletonPath.setAttribute("stroke-width", "1.5");
|
|
593
649
|
svg.appendChild(skeletonPath);
|
|
594
650
|
const skeletonPathA = el("path");
|
|
@@ -620,36 +676,13 @@ function createSVGRenderer(options) {
|
|
|
620
676
|
let scale = 1;
|
|
621
677
|
let offsetX = 0;
|
|
622
678
|
let offsetY = 0;
|
|
623
|
-
function
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
maxX = first.x,
|
|
630
|
-
minY = first.y,
|
|
631
|
-
maxY = first.y;
|
|
632
|
-
for (const p of skeleton2) {
|
|
633
|
-
if (p.x < minX) {
|
|
634
|
-
minX = p.x;
|
|
635
|
-
}
|
|
636
|
-
if (p.x > maxX) {
|
|
637
|
-
maxX = p.x;
|
|
638
|
-
}
|
|
639
|
-
if (p.y < minY) {
|
|
640
|
-
minY = p.y;
|
|
641
|
-
}
|
|
642
|
-
if (p.y > maxY) {
|
|
643
|
-
maxY = p.y;
|
|
644
|
-
}
|
|
679
|
+
function applyBoundaries(skeleton2) {
|
|
680
|
+
const b = computeBoundaries(skeleton2, width, height);
|
|
681
|
+
if (b) {
|
|
682
|
+
scale = b.scale;
|
|
683
|
+
offsetX = b.offsetX;
|
|
684
|
+
offsetY = b.offsetY;
|
|
645
685
|
}
|
|
646
|
-
const w = maxX - minX;
|
|
647
|
-
const h = maxY - minY;
|
|
648
|
-
const scaleX = width / (w * (1 + FIT_PADDING2 * 2));
|
|
649
|
-
const scaleY = height / (h * (1 + FIT_PADDING2 * 2));
|
|
650
|
-
scale = Math.min(scaleX, scaleY);
|
|
651
|
-
offsetX = (width - w * scale) / 2 - minX * scale;
|
|
652
|
-
offsetY = (height - h * scale) / 2 - minY * scale;
|
|
653
686
|
}
|
|
654
687
|
function px(p) {
|
|
655
688
|
return p.x * scale + offsetX;
|
|
@@ -657,26 +690,11 @@ function createSVGRenderer(options) {
|
|
|
657
690
|
function py(p) {
|
|
658
691
|
return p.y * scale + offsetY;
|
|
659
692
|
}
|
|
660
|
-
function pxStr(p) {
|
|
661
|
-
return px(p).toFixed(2);
|
|
662
|
-
}
|
|
663
|
-
function pyStr(p) {
|
|
664
|
-
return py(p).toFixed(2);
|
|
665
|
-
}
|
|
666
693
|
function updateSkeleton(skeleton2) {
|
|
667
|
-
|
|
668
|
-
skeletonPath.setAttribute("d", "");
|
|
669
|
-
return;
|
|
670
|
-
}
|
|
671
|
-
let d = `M${pxStr(skeleton2[0])} ${pyStr(skeleton2[0])}`;
|
|
672
|
-
for (let i = 1; i < skeleton2.length; i++) {
|
|
673
|
-
d += ` L${pxStr(skeleton2[i])} ${pyStr(skeleton2[i])}`;
|
|
674
|
-
}
|
|
675
|
-
d += " Z";
|
|
676
|
-
skeletonPath.setAttribute("d", d);
|
|
694
|
+
skeletonPath.setAttribute("d", pointsToPathString(skeleton2, scale, offsetX, offsetY));
|
|
677
695
|
}
|
|
678
696
|
const skeleton = engine.getSarmalSkeleton();
|
|
679
|
-
|
|
697
|
+
applyBoundaries(skeleton);
|
|
680
698
|
if (!engine.isLiveSkeleton) {
|
|
681
699
|
updateSkeleton(skeleton);
|
|
682
700
|
}
|
|
@@ -688,25 +706,13 @@ function createSVGRenderer(options) {
|
|
|
688
706
|
return;
|
|
689
707
|
}
|
|
690
708
|
for (let i = 0; i < trailCount - 1; i++) {
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
const n0 = computeNormal(trail, i);
|
|
699
|
-
const n1 = computeNormal(trail, i + 1);
|
|
700
|
-
const halfW0 = width2 / 2;
|
|
701
|
-
const halfW1 = nextWidth / 2;
|
|
702
|
-
const l0x = px(curr) + n0.x * halfW0;
|
|
703
|
-
const l0y = py(curr) + n0.y * halfW0;
|
|
704
|
-
const r0x = px(curr) - n0.x * halfW0;
|
|
705
|
-
const r0y = py(curr) - n0.y * halfW0;
|
|
706
|
-
const l1x = px(next) + n1.x * halfW1;
|
|
707
|
-
const l1y = py(next) + n1.y * halfW1;
|
|
708
|
-
const r1x = px(next) - n1.x * halfW1;
|
|
709
|
-
const r1y = py(next) - n1.y * halfW1;
|
|
709
|
+
const { l0x, l0y, r0x, r0y, l1x, l1y, r1x, r1y, opacity } = computeTrailQuad(
|
|
710
|
+
trail,
|
|
711
|
+
i,
|
|
712
|
+
trailCount,
|
|
713
|
+
px,
|
|
714
|
+
py
|
|
715
|
+
);
|
|
710
716
|
const d = `M${l0x.toFixed(2)} ${l0y.toFixed(2)} L${l1x.toFixed(2)} ${l1y.toFixed(2)} L${r1x.toFixed(2)} ${r1y.toFixed(2)} L${r0x.toFixed(2)} ${r0y.toFixed(2)} Z`;
|
|
711
717
|
trailPaths[i].setAttribute("d", d);
|
|
712
718
|
trailPaths[i].setAttribute("fill-opacity", opacity.toFixed(3));
|
|
@@ -727,33 +733,11 @@ function createSVGRenderer(options) {
|
|
|
727
733
|
}
|
|
728
734
|
let animationId = null;
|
|
729
735
|
let lastTime = 0;
|
|
730
|
-
const prefersReducedMotion =
|
|
731
|
-
typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
736
|
+
const prefersReducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
732
737
|
let morphResolve = null;
|
|
733
|
-
let morphDurationMs =
|
|
738
|
+
let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
|
|
734
739
|
let morphTarget = null;
|
|
735
740
|
let morphAlpha = 0;
|
|
736
|
-
function buildSkeletonPath(target, scale2, offsetX2, offsetY2) {
|
|
737
|
-
const period = target.period ?? Math.PI * 2;
|
|
738
|
-
const samples = Math.max(50, Math.round(period * 20));
|
|
739
|
-
const points = [];
|
|
740
|
-
for (let i = 0; i <= samples; i++) {
|
|
741
|
-
const t = (i / samples) * period;
|
|
742
|
-
const p = target.fn(t, 0, {});
|
|
743
|
-
points.push(p);
|
|
744
|
-
}
|
|
745
|
-
if (points.length < 2) {
|
|
746
|
-
return "";
|
|
747
|
-
}
|
|
748
|
-
const px2 = (p) => (p.x * scale2 + offsetX2).toFixed(2);
|
|
749
|
-
const py2 = (p) => (p.y * scale2 + offsetY2).toFixed(2);
|
|
750
|
-
let d = `M${px2(points[0])} ${py2(points[0])}`;
|
|
751
|
-
for (let i = 1; i < points.length; i++) {
|
|
752
|
-
d += ` L${px2(points[i])} ${py2(points[i])}`;
|
|
753
|
-
}
|
|
754
|
-
d += " Z";
|
|
755
|
-
return d;
|
|
756
|
-
}
|
|
757
741
|
function renderFrame() {
|
|
758
742
|
const now = performance.now();
|
|
759
743
|
const dt = Math.min((now - lastTime) / 1e3, 1 / 30);
|
|
@@ -766,16 +750,13 @@ function createSVGRenderer(options) {
|
|
|
766
750
|
skeletonPathA.setAttribute("visibility", "visible");
|
|
767
751
|
skeletonPathA.setAttribute(
|
|
768
752
|
"stroke-opacity",
|
|
769
|
-
String((1 - morphAlpha) *
|
|
753
|
+
String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY)
|
|
770
754
|
);
|
|
771
755
|
}
|
|
772
756
|
if (morphPathBBuilt) {
|
|
773
757
|
skeletonPathB.setAttribute("d", morphPathBBuilt);
|
|
774
758
|
skeletonPathB.setAttribute("visibility", "visible");
|
|
775
|
-
skeletonPathB.setAttribute(
|
|
776
|
-
"stroke-opacity",
|
|
777
|
-
String(morphAlpha * DEFAULT_SKELETON_OPACITY2),
|
|
778
|
-
);
|
|
759
|
+
skeletonPathB.setAttribute("stroke-opacity", String(morphAlpha * DEFAULT_SKELETON_OPACITY));
|
|
779
760
|
}
|
|
780
761
|
if (morphAlpha >= 1) {
|
|
781
762
|
engine.completeMorph();
|
|
@@ -788,7 +769,7 @@ function createSVGRenderer(options) {
|
|
|
788
769
|
skeletonPathA.setAttribute("visibility", "hidden");
|
|
789
770
|
skeletonPathB.setAttribute("visibility", "hidden");
|
|
790
771
|
const newSkeleton = engine.getSarmalSkeleton();
|
|
791
|
-
|
|
772
|
+
applyBoundaries(newSkeleton);
|
|
792
773
|
updateSkeleton(newSkeleton);
|
|
793
774
|
}
|
|
794
775
|
}
|
|
@@ -796,7 +777,7 @@ function createSVGRenderer(options) {
|
|
|
796
777
|
const trailCount = engine.trailCount;
|
|
797
778
|
if (engine.isLiveSkeleton && engine.morphAlpha === null) {
|
|
798
779
|
const liveSkeleton = engine.getSarmalSkeleton();
|
|
799
|
-
|
|
780
|
+
applyBoundaries(liveSkeleton);
|
|
800
781
|
updateSkeleton(liveSkeleton);
|
|
801
782
|
}
|
|
802
783
|
updateTrail(trail, trailCount);
|
|
@@ -845,29 +826,20 @@ function createSVGRenderer(options) {
|
|
|
845
826
|
skeletonPathA.setAttribute("visibility", "hidden");
|
|
846
827
|
skeletonPathB.setAttribute("visibility", "hidden");
|
|
847
828
|
}
|
|
848
|
-
morphDurationMs = options2?.duration ??
|
|
829
|
+
morphDurationMs = options2?.duration ?? DEFAULT_MORPH_DURATION_MS;
|
|
849
830
|
morphTarget = target;
|
|
850
831
|
morphAlpha = 0;
|
|
851
832
|
const currentSkeleton = engine.getSarmalSkeleton();
|
|
852
|
-
|
|
853
|
-
const px2 = (p) => (p.x * scale + offsetX).toFixed(2);
|
|
854
|
-
const py2 = (p) => (p.y * scale + offsetY).toFixed(2);
|
|
855
|
-
morphPathABuilt = `M${px2(currentSkeleton[0])} ${py2(currentSkeleton[0])}`;
|
|
856
|
-
for (let i = 1; i < currentSkeleton.length; i++) {
|
|
857
|
-
morphPathABuilt += ` L${px2(currentSkeleton[i])} ${py2(currentSkeleton[i])}`;
|
|
858
|
-
}
|
|
859
|
-
morphPathABuilt += " Z";
|
|
860
|
-
} else {
|
|
861
|
-
morphPathABuilt = "";
|
|
862
|
-
}
|
|
833
|
+
morphPathABuilt = pointsToPathString(currentSkeleton, scale, offsetX, offsetY);
|
|
863
834
|
engine.startMorph(target, options2?.morphStrategy);
|
|
864
835
|
if (morphTarget) {
|
|
865
|
-
|
|
836
|
+
const targetSkeleton = sampleCurveSkeleton(target);
|
|
837
|
+
morphPathBBuilt = pointsToPathString(targetSkeleton, scale, offsetX, offsetY);
|
|
866
838
|
}
|
|
867
839
|
return new Promise((resolve) => {
|
|
868
840
|
morphResolve = resolve;
|
|
869
841
|
});
|
|
870
|
-
}
|
|
842
|
+
}
|
|
871
843
|
};
|
|
872
844
|
}
|
|
873
845
|
function createSarmalSVG(container, curveDef, options) {
|
|
@@ -879,22 +851,19 @@ function createSarmalSVG(container, curveDef, options) {
|
|
|
879
851
|
// src/curves/artemis2.ts
|
|
880
852
|
var TWO_PI2 = Math.PI * 2;
|
|
881
853
|
function artemis2Fn(t, _time, _params) {
|
|
882
|
-
const a = 0.35,
|
|
883
|
-
|
|
884
|
-
ox = 0.175;
|
|
885
|
-
const s = Math.sin(t),
|
|
886
|
-
c = Math.cos(t);
|
|
854
|
+
const a = 0.35, b = 0.15, ox = 0.175;
|
|
855
|
+
const s = Math.sin(t), c = Math.cos(t);
|
|
887
856
|
const denom = 1 + s * s;
|
|
888
857
|
return {
|
|
889
|
-
x:
|
|
890
|
-
y:
|
|
858
|
+
x: c * (1 + a * c) / denom - ox,
|
|
859
|
+
y: s * c * (1 + b * c) / denom
|
|
891
860
|
};
|
|
892
861
|
}
|
|
893
862
|
var artemis2 = {
|
|
894
863
|
name: "Artemis II",
|
|
895
864
|
fn: artemis2Fn,
|
|
896
865
|
period: TWO_PI2,
|
|
897
|
-
speed: 0.7
|
|
866
|
+
speed: 0.7
|
|
898
867
|
};
|
|
899
868
|
|
|
900
869
|
// src/curves/astroid.ts
|
|
@@ -904,14 +873,14 @@ function astroidFn(t, _time, _params) {
|
|
|
904
873
|
const s = Math.sin(t);
|
|
905
874
|
return {
|
|
906
875
|
x: c * c * c,
|
|
907
|
-
y: s * s * s
|
|
876
|
+
y: s * s * s
|
|
908
877
|
};
|
|
909
878
|
}
|
|
910
879
|
var astroid = {
|
|
911
880
|
name: "Astroid",
|
|
912
881
|
fn: astroidFn,
|
|
913
882
|
period: TWO_PI3,
|
|
914
|
-
speed: 1.1
|
|
883
|
+
speed: 1.1
|
|
915
884
|
};
|
|
916
885
|
|
|
917
886
|
// src/curves/deltoid.ts
|
|
@@ -919,14 +888,14 @@ var TWO_PI4 = Math.PI * 2;
|
|
|
919
888
|
function deltoidFn(t, _time, _params) {
|
|
920
889
|
return {
|
|
921
890
|
x: 2 * Math.cos(t) + Math.cos(2 * t),
|
|
922
|
-
y: 2 * Math.sin(t) - Math.sin(2 * t)
|
|
891
|
+
y: 2 * Math.sin(t) - Math.sin(2 * t)
|
|
923
892
|
};
|
|
924
893
|
}
|
|
925
894
|
var deltoid = {
|
|
926
895
|
name: "Deltoid",
|
|
927
896
|
fn: deltoidFn,
|
|
928
897
|
period: TWO_PI4,
|
|
929
|
-
speed: 0.9
|
|
898
|
+
speed: 0.9
|
|
930
899
|
};
|
|
931
900
|
|
|
932
901
|
// src/curves/epicycloid3.ts
|
|
@@ -934,14 +903,14 @@ var TWO_PI5 = Math.PI * 2;
|
|
|
934
903
|
function epicycloid3Fn(t, _time, _params) {
|
|
935
904
|
return {
|
|
936
905
|
x: 4 * Math.cos(t) - Math.cos(4 * t),
|
|
937
|
-
y: 4 * Math.sin(t) - Math.sin(4 * t)
|
|
906
|
+
y: 4 * Math.sin(t) - Math.sin(4 * t)
|
|
938
907
|
};
|
|
939
908
|
}
|
|
940
909
|
var epicycloid3 = {
|
|
941
910
|
name: "Epicycloid (n=3)",
|
|
942
911
|
fn: epicycloid3Fn,
|
|
943
912
|
period: TWO_PI5,
|
|
944
|
-
speed: 0.75
|
|
913
|
+
speed: 0.75
|
|
945
914
|
};
|
|
946
915
|
|
|
947
916
|
// src/curves/epitrochoid7.ts
|
|
@@ -950,14 +919,14 @@ function epitrochoid7Fn(t, _time, _params) {
|
|
|
950
919
|
const d = 1 + 0.55 * Math.sin(t * 0.5);
|
|
951
920
|
return {
|
|
952
921
|
x: 7 * Math.cos(t) - d * Math.cos(7 * t),
|
|
953
|
-
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
922
|
+
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
954
923
|
};
|
|
955
924
|
}
|
|
956
925
|
function epitrochoid7SkeletonFn(t) {
|
|
957
926
|
const d = 1.275;
|
|
958
927
|
return {
|
|
959
928
|
x: 7 * Math.cos(t) - d * Math.cos(7 * t),
|
|
960
|
-
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
929
|
+
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
961
930
|
};
|
|
962
931
|
}
|
|
963
932
|
var epitrochoid7 = {
|
|
@@ -965,7 +934,7 @@ var epitrochoid7 = {
|
|
|
965
934
|
fn: epitrochoid7Fn,
|
|
966
935
|
period: TWO_PI6,
|
|
967
936
|
speed: 1.4,
|
|
968
|
-
skeletonFn: epitrochoid7SkeletonFn
|
|
937
|
+
skeletonFn: epitrochoid7SkeletonFn
|
|
969
938
|
};
|
|
970
939
|
|
|
971
940
|
// src/curves/lissajous32.ts
|
|
@@ -974,7 +943,7 @@ function lissajous32Fn(t, time, _params) {
|
|
|
974
943
|
const phi = time * 0.45;
|
|
975
944
|
return {
|
|
976
945
|
x: Math.sin(3 * t + phi),
|
|
977
|
-
y: Math.sin(2 * t)
|
|
946
|
+
y: Math.sin(2 * t)
|
|
978
947
|
};
|
|
979
948
|
}
|
|
980
949
|
var lissajous32 = {
|
|
@@ -982,7 +951,7 @@ var lissajous32 = {
|
|
|
982
951
|
fn: lissajous32Fn,
|
|
983
952
|
period: TWO_PI7,
|
|
984
953
|
speed: 2,
|
|
985
|
-
skeleton: "live"
|
|
954
|
+
skeleton: "live"
|
|
986
955
|
};
|
|
987
956
|
|
|
988
957
|
// src/curves/lissajous43.ts
|
|
@@ -991,7 +960,7 @@ function lissajous43Fn(t, time, _params) {
|
|
|
991
960
|
const phi = time * 0.38;
|
|
992
961
|
return {
|
|
993
962
|
x: Math.sin(4 * t + phi),
|
|
994
|
-
y: Math.sin(3 * t)
|
|
963
|
+
y: Math.sin(3 * t)
|
|
995
964
|
};
|
|
996
965
|
}
|
|
997
966
|
var lissajous43 = {
|
|
@@ -999,18 +968,17 @@ var lissajous43 = {
|
|
|
999
968
|
fn: lissajous43Fn,
|
|
1000
969
|
period: TWO_PI8,
|
|
1001
970
|
speed: 1.8,
|
|
1002
|
-
skeleton: "live"
|
|
971
|
+
skeleton: "live"
|
|
1003
972
|
};
|
|
1004
973
|
|
|
1005
974
|
// src/curves/lame.ts
|
|
1006
975
|
var TWO_PI9 = Math.PI * 2;
|
|
1007
976
|
function lameFn(t, time, _params) {
|
|
1008
977
|
const p = 1.75 + 1.25 * Math.sin(time * 0.48);
|
|
1009
|
-
const c = Math.cos(t),
|
|
1010
|
-
s = Math.sin(t);
|
|
978
|
+
const c = Math.cos(t), s = Math.sin(t);
|
|
1011
979
|
return {
|
|
1012
980
|
x: Math.sign(c) * Math.pow(Math.abs(c), p),
|
|
1013
|
-
y: Math.sign(s) * Math.pow(Math.abs(s), p)
|
|
981
|
+
y: Math.sign(s) * Math.pow(Math.abs(s), p)
|
|
1014
982
|
};
|
|
1015
983
|
}
|
|
1016
984
|
var lame = {
|
|
@@ -1018,7 +986,7 @@ var lame = {
|
|
|
1018
986
|
fn: lameFn,
|
|
1019
987
|
period: TWO_PI9,
|
|
1020
988
|
speed: 1,
|
|
1021
|
-
skeleton: "live"
|
|
989
|
+
skeleton: "live"
|
|
1022
990
|
};
|
|
1023
991
|
|
|
1024
992
|
// src/curves/rose3.ts
|
|
@@ -1027,14 +995,14 @@ function rose3Fn(t, _time, _params) {
|
|
|
1027
995
|
const r = Math.cos(3 * t);
|
|
1028
996
|
return {
|
|
1029
997
|
x: r * Math.cos(t),
|
|
1030
|
-
y: r * Math.sin(t)
|
|
998
|
+
y: r * Math.sin(t)
|
|
1031
999
|
};
|
|
1032
1000
|
}
|
|
1033
1001
|
var rose3 = {
|
|
1034
1002
|
name: "Rose (n=3)",
|
|
1035
1003
|
fn: rose3Fn,
|
|
1036
1004
|
period: TWO_PI10,
|
|
1037
|
-
speed: 1.15
|
|
1005
|
+
speed: 1.15
|
|
1038
1006
|
};
|
|
1039
1007
|
|
|
1040
1008
|
// src/curves/rose5.ts
|
|
@@ -1043,14 +1011,14 @@ function rose5Fn(t, _time, _params) {
|
|
|
1043
1011
|
const r = Math.cos(5 * t);
|
|
1044
1012
|
return {
|
|
1045
1013
|
x: r * Math.cos(t),
|
|
1046
|
-
y: r * Math.sin(t)
|
|
1014
|
+
y: r * Math.sin(t)
|
|
1047
1015
|
};
|
|
1048
1016
|
}
|
|
1049
1017
|
var rose5 = {
|
|
1050
1018
|
name: "Rose (n=5)",
|
|
1051
1019
|
fn: rose5Fn,
|
|
1052
1020
|
period: TWO_PI11,
|
|
1053
|
-
speed: 1
|
|
1021
|
+
speed: 1
|
|
1054
1022
|
};
|
|
1055
1023
|
|
|
1056
1024
|
// src/curves/index.ts
|
|
@@ -1064,7 +1032,7 @@ var curves = {
|
|
|
1064
1032
|
lissajous32,
|
|
1065
1033
|
lissajous43,
|
|
1066
1034
|
epicycloid3,
|
|
1067
|
-
lame
|
|
1035
|
+
lame
|
|
1068
1036
|
};
|
|
1069
1037
|
|
|
1070
1038
|
// src/index.ts
|
|
@@ -1091,4 +1059,4 @@ exports.lissajous43 = lissajous43;
|
|
|
1091
1059
|
exports.rose3 = rose3;
|
|
1092
1060
|
exports.rose5 = rose5;
|
|
1093
1061
|
//# sourceMappingURL=index.cjs.map
|
|
1094
|
-
//# sourceMappingURL=index.cjs.map
|
|
1062
|
+
//# sourceMappingURL=index.cjs.map
|