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