@sarmal/core 0.7.0 → 0.8.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 +9 -0
- package/README.md +89 -3
- package/dist/auto-init.cjs +145 -111
- package/dist/auto-init.cjs.map +1 -1
- package/dist/auto-init.js +144 -110
- package/dist/auto-init.js.map +1 -1
- package/dist/index.cjs +181 -168
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +180 -167
- package/dist/index.js.map +1 -1
- package/package.json +12 -2
- package/dist/auto-init.d.cts +0 -2
- package/dist/auto-init.d.ts +0 -2
- package/dist/index.d.cts +0 -262
- package/dist/index.d.ts +0 -262
package/dist/auto-init.js
CHANGED
|
@@ -49,7 +49,7 @@ function resolveCurve(curveDef) {
|
|
|
49
49
|
period: curveDef.period ?? TWO_PI,
|
|
50
50
|
speed: curveDef.speed ?? 1,
|
|
51
51
|
skeleton: curveDef.skeleton,
|
|
52
|
-
skeletonFn: curveDef.skeletonFn
|
|
52
|
+
skeletonFn: curveDef.skeletonFn,
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
function createEngine(curveDef, trailLength = 120) {
|
|
@@ -75,7 +75,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
75
75
|
actualTime += deltaTime;
|
|
76
76
|
if (morphCurveB !== null && _morphAlpha !== null) {
|
|
77
77
|
const a = curve.fn(t, actualTime, {});
|
|
78
|
-
const tB = _morphStrategy === "normalized" ? t / curve.period * morphCurveB.period : t;
|
|
78
|
+
const tB = _morphStrategy === "normalized" ? (t / curve.period) * morphCurveB.period : t;
|
|
79
79
|
const b = morphCurveB.fn(tB, actualTime, {});
|
|
80
80
|
trail.push(a.x + (b.x - a.x) * _morphAlpha, a.y + (b.y - a.y) * _morphAlpha);
|
|
81
81
|
} else {
|
|
@@ -99,14 +99,14 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
99
99
|
trail.clear();
|
|
100
100
|
},
|
|
101
101
|
seek(newT, { clearTrail = false } = {}) {
|
|
102
|
-
t = (newT % curve.period + curve.period) % curve.period;
|
|
102
|
+
t = ((newT % curve.period) + curve.period) % curve.period;
|
|
103
103
|
if (clearTrail) {
|
|
104
104
|
trail.clear();
|
|
105
105
|
}
|
|
106
106
|
},
|
|
107
107
|
seekWithTrail(targetT, { wrap = false, step = curve.period / trailLength } = {}) {
|
|
108
108
|
const advance = curve.speed * step;
|
|
109
|
-
const target = (targetT % curve.period + curve.period) % curve.period;
|
|
109
|
+
const target = ((targetT % curve.period) + curve.period) % curve.period;
|
|
110
110
|
const targetTime = target / curve.speed;
|
|
111
111
|
t = target;
|
|
112
112
|
actualTime = targetTime;
|
|
@@ -132,13 +132,16 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
132
132
|
...frozenB,
|
|
133
133
|
fn: (sampleT, time, params) => {
|
|
134
134
|
const a = frozenA.fn(sampleT, time, params);
|
|
135
|
-
const tB =
|
|
135
|
+
const tB =
|
|
136
|
+
frozenStrategy === "normalized"
|
|
137
|
+
? (sampleT / frozenA.period) * frozenB.period
|
|
138
|
+
: sampleT;
|
|
136
139
|
const b = frozenB.fn(tB, time, params);
|
|
137
140
|
return {
|
|
138
141
|
x: a.x + (b.x - a.x) * frozenAlpha,
|
|
139
|
-
y: a.y + (b.y - a.y) * frozenAlpha
|
|
142
|
+
y: a.y + (b.y - a.y) * frozenAlpha,
|
|
140
143
|
};
|
|
141
|
-
}
|
|
144
|
+
},
|
|
142
145
|
};
|
|
143
146
|
}
|
|
144
147
|
_morphStrategy = strategy;
|
|
@@ -151,7 +154,7 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
151
154
|
completeMorph() {
|
|
152
155
|
if (morphCurveB !== null) {
|
|
153
156
|
if (_morphStrategy === "normalized" && curve.period !== morphCurveB.period) {
|
|
154
|
-
t = t / curve.period * morphCurveB.period;
|
|
157
|
+
t = (t / curve.period) * morphCurveB.period;
|
|
155
158
|
}
|
|
156
159
|
curve = morphCurveB;
|
|
157
160
|
}
|
|
@@ -163,43 +166,74 @@ function createEngine(curveDef, trailLength = 120) {
|
|
|
163
166
|
const points = new Array(steps);
|
|
164
167
|
if (morphCurveB !== null && _morphAlpha !== null) {
|
|
165
168
|
for (let i = 0; i < steps; i++) {
|
|
166
|
-
const sampleT = i / (steps - 1) * curve.period;
|
|
169
|
+
const sampleT = (i / (steps - 1)) * curve.period;
|
|
167
170
|
const a = sampleSkeleton(curve, sampleT);
|
|
168
|
-
const tB =
|
|
171
|
+
const tB =
|
|
172
|
+
_morphStrategy === "normalized"
|
|
173
|
+
? (sampleT / curve.period) * morphCurveB.period
|
|
174
|
+
: sampleT;
|
|
169
175
|
const b = sampleSkeleton(morphCurveB, tB);
|
|
170
176
|
points[i] = {
|
|
171
177
|
x: a.x + (b.x - a.x) * _morphAlpha,
|
|
172
|
-
y: a.y + (b.y - a.y) * _morphAlpha
|
|
178
|
+
y: a.y + (b.y - a.y) * _morphAlpha,
|
|
173
179
|
};
|
|
174
180
|
}
|
|
175
181
|
return points;
|
|
176
182
|
}
|
|
177
183
|
for (let i = 0; i < steps; i++) {
|
|
178
|
-
const sampleT = i / (steps - 1) * curve.period;
|
|
184
|
+
const sampleT = (i / (steps - 1)) * curve.period;
|
|
179
185
|
points[i] = sampleSkeleton(curve, sampleT);
|
|
180
186
|
}
|
|
181
187
|
return points;
|
|
182
|
-
}
|
|
188
|
+
},
|
|
183
189
|
};
|
|
184
190
|
}
|
|
185
191
|
|
|
186
192
|
// src/renderer.ts
|
|
187
193
|
var DEFAULT_MORPH_DURATION_MS = 300;
|
|
188
194
|
var DEFAULT_HEAD_RADIUS = 4;
|
|
189
|
-
var DEFAULT_GLOW_SIZE = 20;
|
|
190
195
|
var DEFAULT_SKELETON_COLOR = "#ffffff";
|
|
191
196
|
var DEFAULT_SKELETON_OPACITY = 0.15;
|
|
192
197
|
var FIT_PADDING = 0.1;
|
|
193
|
-
var TRAIL_BATCH_SIZE = 20;
|
|
194
198
|
var TRAIL_FADE_CURVE = 1.5;
|
|
195
199
|
var TRAIL_MAX_OPACITY = 0.88;
|
|
196
200
|
var TRAIL_MIN_WIDTH = 0.5;
|
|
197
201
|
var TRAIL_MAX_WIDTH = 2.5;
|
|
198
|
-
var GLOW_INNER_EDGE = 0.4;
|
|
199
|
-
var GLOW_FALLOFF_OPACITY = 0.53;
|
|
200
202
|
function hexToRgbComponents(hex) {
|
|
201
203
|
const n = parseInt(hex.slice(1), 16);
|
|
202
|
-
return `${n >> 16},${n >> 8 & 255},${n & 255}`;
|
|
204
|
+
return `${n >> 16},${(n >> 8) & 255},${n & 255}`;
|
|
205
|
+
}
|
|
206
|
+
function computeTangent(trail, i) {
|
|
207
|
+
const count = trail.length;
|
|
208
|
+
if (count < 2) {
|
|
209
|
+
return { x: 1, y: 0 };
|
|
210
|
+
}
|
|
211
|
+
if (i === 0) {
|
|
212
|
+
const dx2 = trail[1].x - trail[0].x;
|
|
213
|
+
const dy2 = trail[1].y - trail[0].y;
|
|
214
|
+
const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
|
|
215
|
+
return { x: dx2 / len2, y: dy2 / len2 };
|
|
216
|
+
}
|
|
217
|
+
if (i === count - 1) {
|
|
218
|
+
const dx2 = trail[count - 1].x - trail[count - 2].x;
|
|
219
|
+
const dy2 = trail[count - 1].y - trail[count - 2].y;
|
|
220
|
+
const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
|
|
221
|
+
return { x: dx2 / len2, y: dy2 / len2 };
|
|
222
|
+
}
|
|
223
|
+
const dx = trail[i + 1].x - trail[i - 1].x;
|
|
224
|
+
const dy = trail[i + 1].y - trail[i - 1].y;
|
|
225
|
+
const len = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
226
|
+
return { x: dx / len, y: dy / len };
|
|
227
|
+
}
|
|
228
|
+
function computeNormal(trail, i) {
|
|
229
|
+
const tangent = computeTangent(trail, i);
|
|
230
|
+
return { x: -tangent.y, y: tangent.x };
|
|
231
|
+
}
|
|
232
|
+
function applyDprSizing(target, logicalWidth, logicalHeight, dpr) {
|
|
233
|
+
target.style.width = `${logicalWidth}px`;
|
|
234
|
+
target.style.height = `${logicalHeight}px`;
|
|
235
|
+
target.width = logicalWidth * dpr;
|
|
236
|
+
target.height = logicalHeight * dpr;
|
|
203
237
|
}
|
|
204
238
|
function createRenderer(options) {
|
|
205
239
|
const canvas = options.canvas;
|
|
@@ -213,10 +247,19 @@ function createRenderer(options) {
|
|
|
213
247
|
trailColor: options.trailColor ?? "#ffffff",
|
|
214
248
|
headColor: options.headColor ?? "#ffffff",
|
|
215
249
|
headRadius: options.headRadius ?? DEFAULT_HEAD_RADIUS,
|
|
216
|
-
glowSize: options.glowSize ?? DEFAULT_GLOW_SIZE
|
|
217
250
|
};
|
|
218
251
|
const trailRgb = hexToRgbComponents(opts.trailColor);
|
|
219
|
-
const
|
|
252
|
+
const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
253
|
+
function setupCanvas() {
|
|
254
|
+
const rect = canvas.getBoundingClientRect();
|
|
255
|
+
const lw = rect.width || 200;
|
|
256
|
+
const lh = rect.height || 200;
|
|
257
|
+
applyDprSizing(canvas, lw, lh, dpr);
|
|
258
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
259
|
+
}
|
|
260
|
+
setupCanvas();
|
|
261
|
+
let logicalWidth = canvas.width / dpr;
|
|
262
|
+
let logicalHeight = canvas.height / dpr;
|
|
220
263
|
let skeleton = [];
|
|
221
264
|
let skeletonCanvas = null;
|
|
222
265
|
let trail = [];
|
|
@@ -230,12 +273,13 @@ function createRenderer(options) {
|
|
|
230
273
|
let morphResolve = null;
|
|
231
274
|
let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
|
|
232
275
|
let morphAlpha = 0;
|
|
233
|
-
let morphBoundsA = null;
|
|
234
|
-
let morphBoundsB = null;
|
|
235
276
|
function computeBoundaries(pts) {
|
|
236
277
|
if (pts.length === 0) return null;
|
|
237
278
|
const first = pts[0];
|
|
238
|
-
let minX = first.x,
|
|
279
|
+
let minX = first.x,
|
|
280
|
+
maxX = first.x,
|
|
281
|
+
minY = first.y,
|
|
282
|
+
maxY = first.y;
|
|
239
283
|
for (const p of pts) {
|
|
240
284
|
if (p.x < minX) minX = p.x;
|
|
241
285
|
if (p.x > maxX) maxX = p.x;
|
|
@@ -244,17 +288,15 @@ function createRenderer(options) {
|
|
|
244
288
|
}
|
|
245
289
|
const width = maxX - minX;
|
|
246
290
|
const height = maxY - minY;
|
|
247
|
-
const
|
|
248
|
-
const
|
|
249
|
-
const scaleX = canvasWidth / (width * (1 + FIT_PADDING * 2));
|
|
250
|
-
const scaleY = canvasHeight / (height * (1 + FIT_PADDING * 2));
|
|
291
|
+
const scaleX = logicalWidth / (width * (1 + FIT_PADDING * 2));
|
|
292
|
+
const scaleY = logicalHeight / (height * (1 + FIT_PADDING * 2));
|
|
251
293
|
const s = Math.min(scaleX, scaleY);
|
|
252
294
|
const boundsWidth = width * s;
|
|
253
295
|
const boundsHeight = height * s;
|
|
254
296
|
return {
|
|
255
297
|
scale: s,
|
|
256
|
-
offsetX: (
|
|
257
|
-
offsetY: (
|
|
298
|
+
offsetX: (logicalWidth - boundsWidth) / 2 - minX * s,
|
|
299
|
+
offsetY: (logicalHeight - boundsHeight) / 2 - minY * s,
|
|
258
300
|
};
|
|
259
301
|
}
|
|
260
302
|
function calculateBoundaries() {
|
|
@@ -269,6 +311,7 @@ function createRenderer(options) {
|
|
|
269
311
|
if (skeleton.length < 2) return;
|
|
270
312
|
skeletonCanvas = new OffscreenCanvas(canvas.width, canvas.height);
|
|
271
313
|
const skeletonCtx = skeletonCanvas.getContext("2d");
|
|
314
|
+
skeletonCtx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
272
315
|
skeletonCtx.strokeStyle = `rgba(${hexToRgbComponents(opts.skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;
|
|
273
316
|
skeletonCtx.lineWidth = 1.5;
|
|
274
317
|
skeletonCtx.beginPath();
|
|
@@ -314,32 +357,41 @@ function createRenderer(options) {
|
|
|
314
357
|
}
|
|
315
358
|
ctx.stroke();
|
|
316
359
|
} else if (skeletonCanvas) {
|
|
317
|
-
ctx.drawImage(skeletonCanvas, 0, 0);
|
|
360
|
+
ctx.drawImage(skeletonCanvas, 0, 0, logicalWidth, logicalHeight);
|
|
318
361
|
}
|
|
319
362
|
}
|
|
320
363
|
function drawTrail() {
|
|
321
364
|
if (trailCount < 2) {
|
|
322
365
|
return;
|
|
323
366
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
const bEnd = Math.min(batchIndex + TRAIL_BATCH_SIZE, trailCount - 1);
|
|
328
|
-
const progress = (batchIndex + bEnd) / 2 / (trailCount - 1);
|
|
367
|
+
for (let i = 0; i < trailCount - 1; i++) {
|
|
368
|
+
const progress = i / (trailCount - 1);
|
|
369
|
+
const nextProgress = (i + 1) / (trailCount - 1);
|
|
329
370
|
const alpha = Math.pow(progress, TRAIL_FADE_CURVE) * TRAIL_MAX_OPACITY;
|
|
330
|
-
const
|
|
371
|
+
const width = TRAIL_MIN_WIDTH + progress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH);
|
|
372
|
+
const nextWidth = TRAIL_MIN_WIDTH + nextProgress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH);
|
|
373
|
+
const curr = trail[i];
|
|
374
|
+
const next = trail[i + 1];
|
|
375
|
+
const n0 = computeNormal(trail, i);
|
|
376
|
+
const n1 = computeNormal(trail, i + 1);
|
|
377
|
+
const halfW0 = width / 2;
|
|
378
|
+
const halfW1 = nextWidth / 2;
|
|
379
|
+
const l0x = curr.x * scale + offsetX + n0.x * halfW0;
|
|
380
|
+
const l0y = curr.y * scale + offsetY + n0.y * halfW0;
|
|
381
|
+
const r0x = curr.x * scale + offsetX - n0.x * halfW0;
|
|
382
|
+
const r0y = curr.y * scale + offsetY - n0.y * halfW0;
|
|
383
|
+
const l1x = next.x * scale + offsetX + n1.x * halfW1;
|
|
384
|
+
const l1y = next.y * scale + offsetY + n1.y * halfW1;
|
|
385
|
+
const r1x = next.x * scale + offsetX - n1.x * halfW1;
|
|
386
|
+
const r1y = next.y * scale + offsetY - n1.y * halfW1;
|
|
387
|
+
ctx.fillStyle = `rgba(${trailRgb},${alpha})`;
|
|
331
388
|
ctx.beginPath();
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
ctx.strokeStyle = `rgba(${trailRgb},${alpha})`;
|
|
341
|
-
ctx.lineWidth = lineWidth;
|
|
342
|
-
ctx.stroke();
|
|
389
|
+
ctx.moveTo(l0x, l0y);
|
|
390
|
+
ctx.lineTo(l1x, l1y);
|
|
391
|
+
ctx.lineTo(r1x, r1y);
|
|
392
|
+
ctx.lineTo(r0x, r0y);
|
|
393
|
+
ctx.closePath();
|
|
394
|
+
ctx.fill();
|
|
343
395
|
}
|
|
344
396
|
}
|
|
345
397
|
function drawHead() {
|
|
@@ -348,14 +400,6 @@ function createRenderer(options) {
|
|
|
348
400
|
}
|
|
349
401
|
const x = head.x * scale + offsetX;
|
|
350
402
|
const y = head.y * scale + offsetY;
|
|
351
|
-
const gradient = ctx.createRadialGradient(x, y, 0, x, y, opts.glowSize);
|
|
352
|
-
gradient.addColorStop(0, opts.headColor);
|
|
353
|
-
gradient.addColorStop(GLOW_INNER_EDGE, headRgbFalloff);
|
|
354
|
-
gradient.addColorStop(1, "transparent");
|
|
355
|
-
ctx.fillStyle = gradient;
|
|
356
|
-
ctx.beginPath();
|
|
357
|
-
ctx.arc(x, y, opts.glowSize, 0, Math.PI * 2);
|
|
358
|
-
ctx.fill();
|
|
359
403
|
ctx.fillStyle = opts.headColor;
|
|
360
404
|
ctx.beginPath();
|
|
361
405
|
ctx.arc(x, y, opts.headRadius, 0, Math.PI * 2);
|
|
@@ -368,20 +412,18 @@ function createRenderer(options) {
|
|
|
368
412
|
if (engine.morphAlpha !== null) {
|
|
369
413
|
morphAlpha = Math.min(1, morphAlpha + deltaTime / (morphDurationMs / 1e3));
|
|
370
414
|
engine.setMorphAlpha(morphAlpha);
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
scale =
|
|
375
|
-
offsetX =
|
|
376
|
-
offsetY =
|
|
415
|
+
const interpolatedSkeleton = engine.getSarmalSkeleton();
|
|
416
|
+
const bounds = computeBoundaries(interpolatedSkeleton);
|
|
417
|
+
if (bounds) {
|
|
418
|
+
scale = bounds.scale;
|
|
419
|
+
offsetX = bounds.offsetX;
|
|
420
|
+
offsetY = bounds.offsetY;
|
|
377
421
|
}
|
|
378
422
|
if (morphAlpha >= 1) {
|
|
379
423
|
engine.completeMorph();
|
|
380
424
|
morphResolve?.();
|
|
381
425
|
morphResolve = null;
|
|
382
426
|
morphAlpha = 0;
|
|
383
|
-
morphBoundsA = null;
|
|
384
|
-
morphBoundsB = null;
|
|
385
427
|
skeleton = engine.getSarmalSkeleton();
|
|
386
428
|
if (!engine.isLiveSkeleton) {
|
|
387
429
|
buildSkeletonCanvas();
|
|
@@ -391,7 +433,7 @@ function createRenderer(options) {
|
|
|
391
433
|
trail = engine.tick(deltaTime);
|
|
392
434
|
trailCount = engine.trailCount;
|
|
393
435
|
head = trailCount > 0 ? trail[trailCount - 1] : null;
|
|
394
|
-
ctx.clearRect(0, 0,
|
|
436
|
+
ctx.clearRect(0, 0, logicalWidth, logicalHeight);
|
|
395
437
|
if (engine.isLiveSkeleton && engine.morphAlpha === null) {
|
|
396
438
|
skeleton = engine.getSarmalSkeleton();
|
|
397
439
|
calculateBoundaries();
|
|
@@ -439,57 +481,48 @@ function createRenderer(options) {
|
|
|
439
481
|
engine.seekWithTrail(t);
|
|
440
482
|
},
|
|
441
483
|
morphTo(target, options2) {
|
|
442
|
-
const interruptBounds = morphResolve !== null ? { scale, offsetX, offsetY } : null;
|
|
443
484
|
if (morphResolve !== null) {
|
|
444
485
|
engine.completeMorph();
|
|
445
486
|
morphResolve();
|
|
446
487
|
morphResolve = null;
|
|
447
488
|
morphAlpha = 0;
|
|
448
|
-
morphBoundsA = null;
|
|
449
|
-
morphBoundsB = null;
|
|
450
489
|
}
|
|
451
490
|
morphDurationMs = options2?.duration ?? DEFAULT_MORPH_DURATION_MS;
|
|
452
491
|
morphAlpha = 0;
|
|
453
|
-
morphBoundsA = interruptBounds ?? computeBoundaries(engine.getSarmalSkeleton()) ?? { scale, offsetX, offsetY };
|
|
454
492
|
engine.startMorph(target, options2?.morphStrategy);
|
|
455
|
-
const period = target.period ?? Math.PI * 2;
|
|
456
|
-
const samples = Math.max(50, Math.round(period * 20));
|
|
457
|
-
const skeletonFn = target.skeletonFn ?? ((t) => target.fn(t, 0, {}));
|
|
458
|
-
const skeletonB = Array.from(
|
|
459
|
-
{ length: samples + 1 },
|
|
460
|
-
(_, i) => skeletonFn(i / samples * period)
|
|
461
|
-
);
|
|
462
|
-
morphBoundsB = computeBoundaries(skeletonB) ?? { scale, offsetX, offsetY };
|
|
463
493
|
return new Promise((resolve) => {
|
|
464
494
|
morphResolve = resolve;
|
|
465
495
|
});
|
|
466
|
-
}
|
|
496
|
+
},
|
|
467
497
|
};
|
|
468
498
|
}
|
|
469
499
|
|
|
470
500
|
// src/curves.ts
|
|
471
501
|
var TWO_PI2 = Math.PI * 2;
|
|
472
502
|
function artemis2(t, _time, _params) {
|
|
473
|
-
const a = 0.35,
|
|
474
|
-
|
|
503
|
+
const a = 0.35,
|
|
504
|
+
b = 0.15,
|
|
505
|
+
ox = 0.175;
|
|
506
|
+
const s = Math.sin(t),
|
|
507
|
+
c = Math.cos(t);
|
|
475
508
|
const denom = 1 + s * s;
|
|
476
509
|
return {
|
|
477
|
-
x: c * (1 + a * c) / denom - ox,
|
|
478
|
-
y: s * c * (1 + b * c) / denom
|
|
510
|
+
x: (c * (1 + a * c)) / denom - ox,
|
|
511
|
+
y: (s * c * (1 + b * c)) / denom,
|
|
479
512
|
};
|
|
480
513
|
}
|
|
481
514
|
function epitrochoid7(t, _time, _params) {
|
|
482
515
|
const d = 1 + 0.55 * Math.sin(t * 0.5);
|
|
483
516
|
return {
|
|
484
517
|
x: 7 * Math.cos(t) - d * Math.cos(7 * t),
|
|
485
|
-
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
518
|
+
y: 7 * Math.sin(t) - d * Math.sin(7 * t),
|
|
486
519
|
};
|
|
487
520
|
}
|
|
488
521
|
function epitrochoid7Skeleton(t) {
|
|
489
522
|
const d = 1.275;
|
|
490
523
|
return {
|
|
491
524
|
x: 7 * Math.cos(t) - d * Math.cos(7 * t),
|
|
492
|
-
y: 7 * Math.sin(t) - d * Math.sin(7 * t)
|
|
525
|
+
y: 7 * Math.sin(t) - d * Math.sin(7 * t),
|
|
493
526
|
};
|
|
494
527
|
}
|
|
495
528
|
function astroid(t, _time, _params) {
|
|
@@ -497,55 +530,56 @@ function astroid(t, _time, _params) {
|
|
|
497
530
|
const s = Math.sin(t);
|
|
498
531
|
return {
|
|
499
532
|
x: c * c * c,
|
|
500
|
-
y: s * s * s
|
|
533
|
+
y: s * s * s,
|
|
501
534
|
};
|
|
502
535
|
}
|
|
503
536
|
function deltoid(t, _time, _params) {
|
|
504
537
|
return {
|
|
505
538
|
x: 2 * Math.cos(t) + Math.cos(2 * t),
|
|
506
|
-
y: 2 * Math.sin(t) - Math.sin(2 * t)
|
|
539
|
+
y: 2 * Math.sin(t) - Math.sin(2 * t),
|
|
507
540
|
};
|
|
508
541
|
}
|
|
509
542
|
function rose5(t, _time, _params) {
|
|
510
543
|
const r = Math.cos(5 * t);
|
|
511
544
|
return {
|
|
512
545
|
x: r * Math.cos(t),
|
|
513
|
-
y: r * Math.sin(t)
|
|
546
|
+
y: r * Math.sin(t),
|
|
514
547
|
};
|
|
515
548
|
}
|
|
516
549
|
function rose3(t, _time, _params) {
|
|
517
550
|
const r = Math.cos(3 * t);
|
|
518
551
|
return {
|
|
519
552
|
x: r * Math.cos(t),
|
|
520
|
-
y: r * Math.sin(t)
|
|
553
|
+
y: r * Math.sin(t),
|
|
521
554
|
};
|
|
522
555
|
}
|
|
523
556
|
function lissajous32(t, time, _params) {
|
|
524
557
|
const phi = time * 0.45;
|
|
525
558
|
return {
|
|
526
559
|
x: Math.sin(3 * t + phi),
|
|
527
|
-
y: Math.sin(2 * t)
|
|
560
|
+
y: Math.sin(2 * t),
|
|
528
561
|
};
|
|
529
562
|
}
|
|
530
563
|
function lissajous43(t, time, _params) {
|
|
531
564
|
const phi = time * 0.38;
|
|
532
565
|
return {
|
|
533
566
|
x: Math.sin(4 * t + phi),
|
|
534
|
-
y: Math.sin(3 * t)
|
|
567
|
+
y: Math.sin(3 * t),
|
|
535
568
|
};
|
|
536
569
|
}
|
|
537
570
|
function epicycloid3(t, _time, _params) {
|
|
538
571
|
return {
|
|
539
572
|
x: 4 * Math.cos(t) - Math.cos(4 * t),
|
|
540
|
-
y: 4 * Math.sin(t) - Math.sin(4 * t)
|
|
573
|
+
y: 4 * Math.sin(t) - Math.sin(4 * t),
|
|
541
574
|
};
|
|
542
575
|
}
|
|
543
576
|
function lame(t, time, _params) {
|
|
544
577
|
const p = 1.75 + 1.25 * Math.sin(time * 0.48);
|
|
545
|
-
const c = Math.cos(t),
|
|
578
|
+
const c = Math.cos(t),
|
|
579
|
+
s = Math.sin(t);
|
|
546
580
|
return {
|
|
547
581
|
x: Math.sign(c) * Math.pow(Math.abs(c), p),
|
|
548
|
-
y: Math.sign(s) * Math.pow(Math.abs(s), p)
|
|
582
|
+
y: Math.sign(s) * Math.pow(Math.abs(s), p),
|
|
549
583
|
};
|
|
550
584
|
}
|
|
551
585
|
var curves = {
|
|
@@ -553,66 +587,66 @@ var curves = {
|
|
|
553
587
|
name: "Artemis II",
|
|
554
588
|
fn: artemis2,
|
|
555
589
|
period: TWO_PI2,
|
|
556
|
-
speed: 0.7
|
|
590
|
+
speed: 0.7,
|
|
557
591
|
},
|
|
558
592
|
epitrochoid7: {
|
|
559
593
|
name: "Epitrochoid",
|
|
560
594
|
fn: epitrochoid7,
|
|
561
595
|
period: TWO_PI2,
|
|
562
596
|
speed: 1.4,
|
|
563
|
-
skeletonFn: epitrochoid7Skeleton
|
|
597
|
+
skeletonFn: epitrochoid7Skeleton,
|
|
564
598
|
},
|
|
565
599
|
astroid: {
|
|
566
600
|
name: "Astroid",
|
|
567
601
|
fn: astroid,
|
|
568
602
|
period: TWO_PI2,
|
|
569
|
-
speed: 1.1
|
|
603
|
+
speed: 1.1,
|
|
570
604
|
},
|
|
571
605
|
deltoid: {
|
|
572
606
|
name: "Deltoid",
|
|
573
607
|
fn: deltoid,
|
|
574
608
|
period: TWO_PI2,
|
|
575
|
-
speed: 0.9
|
|
609
|
+
speed: 0.9,
|
|
576
610
|
},
|
|
577
611
|
rose5: {
|
|
578
612
|
name: "Rose (n=5)",
|
|
579
613
|
fn: rose5,
|
|
580
614
|
period: TWO_PI2,
|
|
581
|
-
speed: 1
|
|
615
|
+
speed: 1,
|
|
582
616
|
},
|
|
583
617
|
rose3: {
|
|
584
618
|
name: "Rose (n=3)",
|
|
585
619
|
fn: rose3,
|
|
586
620
|
period: TWO_PI2,
|
|
587
|
-
speed: 1.15
|
|
621
|
+
speed: 1.15,
|
|
588
622
|
},
|
|
589
623
|
lissajous32: {
|
|
590
624
|
name: "Lissajous 3:2",
|
|
591
625
|
fn: lissajous32,
|
|
592
626
|
period: TWO_PI2,
|
|
593
627
|
speed: 2,
|
|
594
|
-
skeleton: "live"
|
|
628
|
+
skeleton: "live",
|
|
595
629
|
},
|
|
596
630
|
lissajous43: {
|
|
597
631
|
name: "Lissajous 4:3",
|
|
598
632
|
fn: lissajous43,
|
|
599
633
|
period: TWO_PI2,
|
|
600
634
|
speed: 1.8,
|
|
601
|
-
skeleton: "live"
|
|
635
|
+
skeleton: "live",
|
|
602
636
|
},
|
|
603
637
|
epicycloid3: {
|
|
604
638
|
name: "Epicycloid (n=3)",
|
|
605
639
|
fn: epicycloid3,
|
|
606
640
|
period: TWO_PI2,
|
|
607
|
-
speed: 0.75
|
|
641
|
+
speed: 0.75,
|
|
608
642
|
},
|
|
609
643
|
lame: {
|
|
610
644
|
name: "Lam\xE9 Curve",
|
|
611
645
|
fn: lame,
|
|
612
646
|
period: TWO_PI2,
|
|
613
647
|
speed: 1,
|
|
614
|
-
skeleton: "live"
|
|
615
|
-
}
|
|
648
|
+
skeleton: "live",
|
|
649
|
+
},
|
|
616
650
|
};
|
|
617
651
|
|
|
618
652
|
// src/index.ts
|
|
@@ -635,12 +669,12 @@ function init() {
|
|
|
635
669
|
return console.error(`[sarmal] "${curveName}" is not a valid curve name`);
|
|
636
670
|
}
|
|
637
671
|
const sarmal = createSarmal(canvas, curveDef, {
|
|
638
|
-
...canvas.dataset.trailColor && { trailColor: canvas.dataset.trailColor },
|
|
639
|
-
...canvas.dataset.skeletonColor && { skeletonColor: canvas.dataset.skeletonColor },
|
|
640
|
-
...canvas.dataset.headColor && { headColor: canvas.dataset.headColor },
|
|
641
|
-
...canvas.dataset.headRadius && { headRadius: parseFloat(canvas.dataset.headRadius) },
|
|
642
|
-
...canvas.dataset.glowSize && { glowSize: parseInt(canvas.dataset.glowSize, 10) },
|
|
643
|
-
...canvas.dataset.trailLength && { trailLength: parseInt(canvas.dataset.trailLength, 10) }
|
|
672
|
+
...(canvas.dataset.trailColor && { trailColor: canvas.dataset.trailColor }),
|
|
673
|
+
...(canvas.dataset.skeletonColor && { skeletonColor: canvas.dataset.skeletonColor }),
|
|
674
|
+
...(canvas.dataset.headColor && { headColor: canvas.dataset.headColor }),
|
|
675
|
+
...(canvas.dataset.headRadius && { headRadius: parseFloat(canvas.dataset.headRadius) }),
|
|
676
|
+
...(canvas.dataset.glowSize && { glowSize: parseInt(canvas.dataset.glowSize, 10) }),
|
|
677
|
+
...(canvas.dataset.trailLength && { trailLength: parseInt(canvas.dataset.trailLength, 10) }),
|
|
644
678
|
});
|
|
645
679
|
sarmal.start();
|
|
646
680
|
});
|
|
@@ -651,4 +685,4 @@ if (document.readyState === "loading") {
|
|
|
651
685
|
init();
|
|
652
686
|
}
|
|
653
687
|
//# sourceMappingURL=auto-init.js.map
|
|
654
|
-
//# sourceMappingURL=auto-init.js.map
|
|
688
|
+
//# sourceMappingURL=auto-init.js.map
|