@shotstack/shotstack-canvas 2.1.2 → 2.1.4
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/entry.node.cjs +58 -30
- package/dist/entry.node.js +58 -30
- package/dist/entry.web.js +58 -30
- package/package.json +1 -1
package/dist/entry.node.cjs
CHANGED
|
@@ -1851,8 +1851,8 @@ async function buildDrawOps(p) {
|
|
|
1851
1851
|
const canvasCenterY = p.canvas.height / 2;
|
|
1852
1852
|
const bgX = canvasCenterX - contentWidth / 2;
|
|
1853
1853
|
const bgY = canvasCenterY - contentHeight / 2;
|
|
1854
|
-
const maxRadius = Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2;
|
|
1855
|
-
const outerRadius = Math.min(borderRadius, maxRadius);
|
|
1854
|
+
const maxRadius = Math.max(0, Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2);
|
|
1855
|
+
const outerRadius = Math.max(0, Math.min(borderRadius, maxRadius));
|
|
1856
1856
|
const innerRadius = Math.max(0, outerRadius - halfBorder);
|
|
1857
1857
|
if (p.background?.color) {
|
|
1858
1858
|
ops.push({
|
|
@@ -2727,7 +2727,8 @@ function calculatePopState(ctx, activeScale, speed) {
|
|
|
2727
2727
|
return {
|
|
2728
2728
|
scale: 0.5,
|
|
2729
2729
|
opacity: 0,
|
|
2730
|
-
isActive: false
|
|
2730
|
+
isActive: false,
|
|
2731
|
+
fillProgress: 0
|
|
2731
2732
|
};
|
|
2732
2733
|
}
|
|
2733
2734
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
@@ -2735,28 +2736,33 @@ function calculatePopState(ctx, activeScale, speed) {
|
|
|
2735
2736
|
const progress = calculateAnimationProgress(adjustedCtx);
|
|
2736
2737
|
const easedProgress = easeOutBack(progress);
|
|
2737
2738
|
const startScale = 0.5;
|
|
2738
|
-
const
|
|
2739
|
+
const isActive = isWordActive(ctx);
|
|
2740
|
+
const endScale = isActive ? activeScale : 1;
|
|
2739
2741
|
const scale = startScale + (endScale - startScale) * easedProgress;
|
|
2740
2742
|
return {
|
|
2741
2743
|
scale: Math.min(scale, activeScale),
|
|
2742
2744
|
opacity: easedProgress,
|
|
2743
|
-
isActive
|
|
2745
|
+
isActive,
|
|
2746
|
+
fillProgress: isActive ? 1 : 0
|
|
2744
2747
|
};
|
|
2745
2748
|
}
|
|
2746
2749
|
function calculateFadeState(ctx, speed) {
|
|
2747
2750
|
if (ctx.currentTime < ctx.wordStart) {
|
|
2748
2751
|
return {
|
|
2749
2752
|
opacity: 0,
|
|
2750
|
-
isActive: false
|
|
2753
|
+
isActive: false,
|
|
2754
|
+
fillProgress: 0
|
|
2751
2755
|
};
|
|
2752
2756
|
}
|
|
2753
2757
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
2754
2758
|
const adjustedCtx = { ...ctx, animationDuration: adjustedDuration };
|
|
2755
2759
|
const progress = calculateAnimationProgress(adjustedCtx);
|
|
2756
2760
|
const easedProgress = easeInOutQuad(progress);
|
|
2761
|
+
const isActive = isWordActive(ctx);
|
|
2757
2762
|
return {
|
|
2758
2763
|
opacity: easedProgress,
|
|
2759
|
-
isActive
|
|
2764
|
+
isActive,
|
|
2765
|
+
fillProgress: isActive ? 1 : 0
|
|
2760
2766
|
};
|
|
2761
2767
|
}
|
|
2762
2768
|
function calculateSlideState(ctx, direction, speed, fontSize) {
|
|
@@ -2767,7 +2773,8 @@ function calculateSlideState(ctx, direction, speed, fontSize) {
|
|
|
2767
2773
|
translateX: offset2.x,
|
|
2768
2774
|
translateY: offset2.y,
|
|
2769
2775
|
opacity: 0,
|
|
2770
|
-
isActive: false
|
|
2776
|
+
isActive: false,
|
|
2777
|
+
fillProgress: 0
|
|
2771
2778
|
};
|
|
2772
2779
|
}
|
|
2773
2780
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
@@ -2777,11 +2784,13 @@ function calculateSlideState(ctx, direction, speed, fontSize) {
|
|
|
2777
2784
|
const offset = getDirectionOffset(direction, slideDistance);
|
|
2778
2785
|
const translateX = offset.x * (1 - easedProgress);
|
|
2779
2786
|
const translateY = offset.y * (1 - easedProgress);
|
|
2787
|
+
const isActive = isWordActive(ctx);
|
|
2780
2788
|
return {
|
|
2781
2789
|
translateX,
|
|
2782
2790
|
translateY,
|
|
2783
2791
|
opacity: easeOutQuad2(progress),
|
|
2784
|
-
isActive
|
|
2792
|
+
isActive,
|
|
2793
|
+
fillProgress: isActive ? 1 : 0
|
|
2785
2794
|
};
|
|
2786
2795
|
}
|
|
2787
2796
|
function getDirectionOffset(direction, distance) {
|
|
@@ -2802,17 +2811,20 @@ function calculateBounceState(ctx, speed, fontSize) {
|
|
|
2802
2811
|
return {
|
|
2803
2812
|
translateY: -bounceDistance,
|
|
2804
2813
|
opacity: 0,
|
|
2805
|
-
isActive: false
|
|
2814
|
+
isActive: false,
|
|
2815
|
+
fillProgress: 0
|
|
2806
2816
|
};
|
|
2807
2817
|
}
|
|
2808
2818
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
2809
2819
|
const adjustedCtx = { ...ctx, animationDuration: adjustedDuration };
|
|
2810
2820
|
const progress = calculateAnimationProgress(adjustedCtx);
|
|
2811
2821
|
const easedProgress = easeOutBounce(progress);
|
|
2822
|
+
const isActive = isWordActive(ctx);
|
|
2812
2823
|
return {
|
|
2813
2824
|
translateY: -bounceDistance * (1 - easedProgress),
|
|
2814
2825
|
opacity: easeOutQuad2(progress),
|
|
2815
|
-
isActive
|
|
2826
|
+
isActive,
|
|
2827
|
+
fillProgress: isActive ? 1 : 0
|
|
2816
2828
|
};
|
|
2817
2829
|
}
|
|
2818
2830
|
function calculateTypewriterState(ctx, charCount, speed) {
|
|
@@ -2928,20 +2940,30 @@ var WORD_BG_PADDING_RATIO = 0.12;
|
|
|
2928
2940
|
function extractFontConfig(asset) {
|
|
2929
2941
|
const font = asset.font;
|
|
2930
2942
|
const active = asset.active?.font;
|
|
2943
|
+
const hasActiveConfig = asset.active !== void 0;
|
|
2931
2944
|
const baseColor = font?.color ?? "#ffffff";
|
|
2932
|
-
const
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2945
|
+
const baseOpacity = font?.opacity ?? 1;
|
|
2946
|
+
let activeColor;
|
|
2947
|
+
let activeOpacity;
|
|
2948
|
+
if (!hasActiveConfig) {
|
|
2949
|
+
activeColor = baseColor;
|
|
2950
|
+
activeOpacity = baseOpacity;
|
|
2951
|
+
} else {
|
|
2952
|
+
const explicitActiveColor = active?.color;
|
|
2953
|
+
const animStyle = asset.wordAnimation?.style ?? "highlight";
|
|
2954
|
+
const isFillAnimation = animStyle === "karaoke" || animStyle === "highlight";
|
|
2955
|
+
const DEFAULT_ACTIVE_COLOR = "#ffff00";
|
|
2956
|
+
activeColor = explicitActiveColor ?? (isFillAnimation ? DEFAULT_ACTIVE_COLOR : baseColor);
|
|
2957
|
+
activeOpacity = active?.opacity ?? baseOpacity;
|
|
2958
|
+
}
|
|
2937
2959
|
return {
|
|
2938
2960
|
family: font?.family ?? "Roboto",
|
|
2939
2961
|
size: font?.size ?? 24,
|
|
2940
2962
|
weight: String(font?.weight ?? "400"),
|
|
2941
2963
|
baseColor,
|
|
2942
2964
|
activeColor,
|
|
2943
|
-
baseOpacity
|
|
2944
|
-
activeOpacity
|
|
2965
|
+
baseOpacity,
|
|
2966
|
+
activeOpacity,
|
|
2945
2967
|
letterSpacing: asset.style?.letterSpacing ?? 0
|
|
2946
2968
|
};
|
|
2947
2969
|
}
|
|
@@ -3478,9 +3500,14 @@ async function createNodePainter(opts) {
|
|
|
3478
3500
|
i++;
|
|
3479
3501
|
}
|
|
3480
3502
|
renderToBoth((context) => {
|
|
3503
|
+
const bgSortedOps = [...captionWordOps].sort((a, b) => {
|
|
3504
|
+
const dy = Math.round(a.y) - Math.round(b.y);
|
|
3505
|
+
if (dy !== 0) return dy;
|
|
3506
|
+
return a.x + a.transform.translateX - (b.x + b.transform.translateX);
|
|
3507
|
+
});
|
|
3481
3508
|
let bgIdx = 0;
|
|
3482
|
-
while (bgIdx <
|
|
3483
|
-
const wordOp =
|
|
3509
|
+
while (bgIdx < bgSortedOps.length) {
|
|
3510
|
+
const wordOp = bgSortedOps[bgIdx];
|
|
3484
3511
|
if (!wordOp.background) {
|
|
3485
3512
|
bgIdx++;
|
|
3486
3513
|
continue;
|
|
@@ -3492,13 +3519,12 @@ async function createNodePainter(opts) {
|
|
|
3492
3519
|
}
|
|
3493
3520
|
const mergeGroup = [wordOp];
|
|
3494
3521
|
let nextIdx = bgIdx + 1;
|
|
3495
|
-
while (nextIdx <
|
|
3496
|
-
const nextWord =
|
|
3522
|
+
while (nextIdx < bgSortedOps.length) {
|
|
3523
|
+
const nextWord = bgSortedOps[nextIdx];
|
|
3497
3524
|
if (!nextWord.background) break;
|
|
3498
3525
|
const nextDisplay = getVisibleText(nextWord.text, nextWord.visibleCharacters, nextWord.isRTL);
|
|
3499
3526
|
if (nextDisplay.length === 0) break;
|
|
3500
3527
|
if (Math.round(nextWord.y) !== Math.round(wordOp.y)) break;
|
|
3501
|
-
if (nextWord.background.color !== wordOp.background.color) break;
|
|
3502
3528
|
mergeGroup.push(nextWord);
|
|
3503
3529
|
nextIdx++;
|
|
3504
3530
|
}
|
|
@@ -3526,11 +3552,13 @@ async function createNodePainter(opts) {
|
|
|
3526
3552
|
const bgY = -bgAscent - firstBg.padding;
|
|
3527
3553
|
const bgW = mergedWidth + firstBg.padding * 2;
|
|
3528
3554
|
const bgH = bgTextHeight + firstBg.padding * 2;
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3555
|
+
if (bgW > 0 && bgH > 0) {
|
|
3556
|
+
const bgC = parseHex6(firstBg.color, firstBg.opacity);
|
|
3557
|
+
context.fillStyle = `rgba(${bgC.r},${bgC.g},${bgC.b},${bgC.a})`;
|
|
3558
|
+
context.beginPath();
|
|
3559
|
+
roundRectPath(context, bgX, bgY, bgW, bgH, firstBg.borderRadius);
|
|
3560
|
+
context.fill();
|
|
3561
|
+
}
|
|
3534
3562
|
context.restore();
|
|
3535
3563
|
bgIdx = nextIdx;
|
|
3536
3564
|
}
|
|
@@ -3827,8 +3855,8 @@ function computePathBounds2(d) {
|
|
|
3827
3855
|
};
|
|
3828
3856
|
}
|
|
3829
3857
|
function roundRectPath(ctx, x, y, w, h, r) {
|
|
3830
|
-
const maxRadius = Math.min(w, h) / 2;
|
|
3831
|
-
const radius = Math.min(r, maxRadius);
|
|
3858
|
+
const maxRadius = Math.max(0, Math.min(w, h) / 2);
|
|
3859
|
+
const radius = Math.max(0, Math.min(r, maxRadius));
|
|
3832
3860
|
ctx.moveTo(x + radius, y);
|
|
3833
3861
|
ctx.arcTo(x + w, y, x + w, y + h, radius);
|
|
3834
3862
|
ctx.arcTo(x + w, y + h, x, y + h, radius);
|
package/dist/entry.node.js
CHANGED
|
@@ -1448,8 +1448,8 @@ async function buildDrawOps(p) {
|
|
|
1448
1448
|
const canvasCenterY = p.canvas.height / 2;
|
|
1449
1449
|
const bgX = canvasCenterX - contentWidth / 2;
|
|
1450
1450
|
const bgY = canvasCenterY - contentHeight / 2;
|
|
1451
|
-
const maxRadius = Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2;
|
|
1452
|
-
const outerRadius = Math.min(borderRadius, maxRadius);
|
|
1451
|
+
const maxRadius = Math.max(0, Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2);
|
|
1452
|
+
const outerRadius = Math.max(0, Math.min(borderRadius, maxRadius));
|
|
1453
1453
|
const innerRadius = Math.max(0, outerRadius - halfBorder);
|
|
1454
1454
|
if (p.background?.color) {
|
|
1455
1455
|
ops.push({
|
|
@@ -2324,7 +2324,8 @@ function calculatePopState(ctx, activeScale, speed) {
|
|
|
2324
2324
|
return {
|
|
2325
2325
|
scale: 0.5,
|
|
2326
2326
|
opacity: 0,
|
|
2327
|
-
isActive: false
|
|
2327
|
+
isActive: false,
|
|
2328
|
+
fillProgress: 0
|
|
2328
2329
|
};
|
|
2329
2330
|
}
|
|
2330
2331
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
@@ -2332,28 +2333,33 @@ function calculatePopState(ctx, activeScale, speed) {
|
|
|
2332
2333
|
const progress = calculateAnimationProgress(adjustedCtx);
|
|
2333
2334
|
const easedProgress = easeOutBack(progress);
|
|
2334
2335
|
const startScale = 0.5;
|
|
2335
|
-
const
|
|
2336
|
+
const isActive = isWordActive(ctx);
|
|
2337
|
+
const endScale = isActive ? activeScale : 1;
|
|
2336
2338
|
const scale = startScale + (endScale - startScale) * easedProgress;
|
|
2337
2339
|
return {
|
|
2338
2340
|
scale: Math.min(scale, activeScale),
|
|
2339
2341
|
opacity: easedProgress,
|
|
2340
|
-
isActive
|
|
2342
|
+
isActive,
|
|
2343
|
+
fillProgress: isActive ? 1 : 0
|
|
2341
2344
|
};
|
|
2342
2345
|
}
|
|
2343
2346
|
function calculateFadeState(ctx, speed) {
|
|
2344
2347
|
if (ctx.currentTime < ctx.wordStart) {
|
|
2345
2348
|
return {
|
|
2346
2349
|
opacity: 0,
|
|
2347
|
-
isActive: false
|
|
2350
|
+
isActive: false,
|
|
2351
|
+
fillProgress: 0
|
|
2348
2352
|
};
|
|
2349
2353
|
}
|
|
2350
2354
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
2351
2355
|
const adjustedCtx = { ...ctx, animationDuration: adjustedDuration };
|
|
2352
2356
|
const progress = calculateAnimationProgress(adjustedCtx);
|
|
2353
2357
|
const easedProgress = easeInOutQuad(progress);
|
|
2358
|
+
const isActive = isWordActive(ctx);
|
|
2354
2359
|
return {
|
|
2355
2360
|
opacity: easedProgress,
|
|
2356
|
-
isActive
|
|
2361
|
+
isActive,
|
|
2362
|
+
fillProgress: isActive ? 1 : 0
|
|
2357
2363
|
};
|
|
2358
2364
|
}
|
|
2359
2365
|
function calculateSlideState(ctx, direction, speed, fontSize) {
|
|
@@ -2364,7 +2370,8 @@ function calculateSlideState(ctx, direction, speed, fontSize) {
|
|
|
2364
2370
|
translateX: offset2.x,
|
|
2365
2371
|
translateY: offset2.y,
|
|
2366
2372
|
opacity: 0,
|
|
2367
|
-
isActive: false
|
|
2373
|
+
isActive: false,
|
|
2374
|
+
fillProgress: 0
|
|
2368
2375
|
};
|
|
2369
2376
|
}
|
|
2370
2377
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
@@ -2374,11 +2381,13 @@ function calculateSlideState(ctx, direction, speed, fontSize) {
|
|
|
2374
2381
|
const offset = getDirectionOffset(direction, slideDistance);
|
|
2375
2382
|
const translateX = offset.x * (1 - easedProgress);
|
|
2376
2383
|
const translateY = offset.y * (1 - easedProgress);
|
|
2384
|
+
const isActive = isWordActive(ctx);
|
|
2377
2385
|
return {
|
|
2378
2386
|
translateX,
|
|
2379
2387
|
translateY,
|
|
2380
2388
|
opacity: easeOutQuad2(progress),
|
|
2381
|
-
isActive
|
|
2389
|
+
isActive,
|
|
2390
|
+
fillProgress: isActive ? 1 : 0
|
|
2382
2391
|
};
|
|
2383
2392
|
}
|
|
2384
2393
|
function getDirectionOffset(direction, distance) {
|
|
@@ -2399,17 +2408,20 @@ function calculateBounceState(ctx, speed, fontSize) {
|
|
|
2399
2408
|
return {
|
|
2400
2409
|
translateY: -bounceDistance,
|
|
2401
2410
|
opacity: 0,
|
|
2402
|
-
isActive: false
|
|
2411
|
+
isActive: false,
|
|
2412
|
+
fillProgress: 0
|
|
2403
2413
|
};
|
|
2404
2414
|
}
|
|
2405
2415
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
2406
2416
|
const adjustedCtx = { ...ctx, animationDuration: adjustedDuration };
|
|
2407
2417
|
const progress = calculateAnimationProgress(adjustedCtx);
|
|
2408
2418
|
const easedProgress = easeOutBounce(progress);
|
|
2419
|
+
const isActive = isWordActive(ctx);
|
|
2409
2420
|
return {
|
|
2410
2421
|
translateY: -bounceDistance * (1 - easedProgress),
|
|
2411
2422
|
opacity: easeOutQuad2(progress),
|
|
2412
|
-
isActive
|
|
2423
|
+
isActive,
|
|
2424
|
+
fillProgress: isActive ? 1 : 0
|
|
2413
2425
|
};
|
|
2414
2426
|
}
|
|
2415
2427
|
function calculateTypewriterState(ctx, charCount, speed) {
|
|
@@ -2525,20 +2537,30 @@ var WORD_BG_PADDING_RATIO = 0.12;
|
|
|
2525
2537
|
function extractFontConfig(asset) {
|
|
2526
2538
|
const font = asset.font;
|
|
2527
2539
|
const active = asset.active?.font;
|
|
2540
|
+
const hasActiveConfig = asset.active !== void 0;
|
|
2528
2541
|
const baseColor = font?.color ?? "#ffffff";
|
|
2529
|
-
const
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2542
|
+
const baseOpacity = font?.opacity ?? 1;
|
|
2543
|
+
let activeColor;
|
|
2544
|
+
let activeOpacity;
|
|
2545
|
+
if (!hasActiveConfig) {
|
|
2546
|
+
activeColor = baseColor;
|
|
2547
|
+
activeOpacity = baseOpacity;
|
|
2548
|
+
} else {
|
|
2549
|
+
const explicitActiveColor = active?.color;
|
|
2550
|
+
const animStyle = asset.wordAnimation?.style ?? "highlight";
|
|
2551
|
+
const isFillAnimation = animStyle === "karaoke" || animStyle === "highlight";
|
|
2552
|
+
const DEFAULT_ACTIVE_COLOR = "#ffff00";
|
|
2553
|
+
activeColor = explicitActiveColor ?? (isFillAnimation ? DEFAULT_ACTIVE_COLOR : baseColor);
|
|
2554
|
+
activeOpacity = active?.opacity ?? baseOpacity;
|
|
2555
|
+
}
|
|
2534
2556
|
return {
|
|
2535
2557
|
family: font?.family ?? "Roboto",
|
|
2536
2558
|
size: font?.size ?? 24,
|
|
2537
2559
|
weight: String(font?.weight ?? "400"),
|
|
2538
2560
|
baseColor,
|
|
2539
2561
|
activeColor,
|
|
2540
|
-
baseOpacity
|
|
2541
|
-
activeOpacity
|
|
2562
|
+
baseOpacity,
|
|
2563
|
+
activeOpacity,
|
|
2542
2564
|
letterSpacing: asset.style?.letterSpacing ?? 0
|
|
2543
2565
|
};
|
|
2544
2566
|
}
|
|
@@ -3075,9 +3097,14 @@ async function createNodePainter(opts) {
|
|
|
3075
3097
|
i++;
|
|
3076
3098
|
}
|
|
3077
3099
|
renderToBoth((context) => {
|
|
3100
|
+
const bgSortedOps = [...captionWordOps].sort((a, b) => {
|
|
3101
|
+
const dy = Math.round(a.y) - Math.round(b.y);
|
|
3102
|
+
if (dy !== 0) return dy;
|
|
3103
|
+
return a.x + a.transform.translateX - (b.x + b.transform.translateX);
|
|
3104
|
+
});
|
|
3078
3105
|
let bgIdx = 0;
|
|
3079
|
-
while (bgIdx <
|
|
3080
|
-
const wordOp =
|
|
3106
|
+
while (bgIdx < bgSortedOps.length) {
|
|
3107
|
+
const wordOp = bgSortedOps[bgIdx];
|
|
3081
3108
|
if (!wordOp.background) {
|
|
3082
3109
|
bgIdx++;
|
|
3083
3110
|
continue;
|
|
@@ -3089,13 +3116,12 @@ async function createNodePainter(opts) {
|
|
|
3089
3116
|
}
|
|
3090
3117
|
const mergeGroup = [wordOp];
|
|
3091
3118
|
let nextIdx = bgIdx + 1;
|
|
3092
|
-
while (nextIdx <
|
|
3093
|
-
const nextWord =
|
|
3119
|
+
while (nextIdx < bgSortedOps.length) {
|
|
3120
|
+
const nextWord = bgSortedOps[nextIdx];
|
|
3094
3121
|
if (!nextWord.background) break;
|
|
3095
3122
|
const nextDisplay = getVisibleText(nextWord.text, nextWord.visibleCharacters, nextWord.isRTL);
|
|
3096
3123
|
if (nextDisplay.length === 0) break;
|
|
3097
3124
|
if (Math.round(nextWord.y) !== Math.round(wordOp.y)) break;
|
|
3098
|
-
if (nextWord.background.color !== wordOp.background.color) break;
|
|
3099
3125
|
mergeGroup.push(nextWord);
|
|
3100
3126
|
nextIdx++;
|
|
3101
3127
|
}
|
|
@@ -3123,11 +3149,13 @@ async function createNodePainter(opts) {
|
|
|
3123
3149
|
const bgY = -bgAscent - firstBg.padding;
|
|
3124
3150
|
const bgW = mergedWidth + firstBg.padding * 2;
|
|
3125
3151
|
const bgH = bgTextHeight + firstBg.padding * 2;
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3152
|
+
if (bgW > 0 && bgH > 0) {
|
|
3153
|
+
const bgC = parseHex6(firstBg.color, firstBg.opacity);
|
|
3154
|
+
context.fillStyle = `rgba(${bgC.r},${bgC.g},${bgC.b},${bgC.a})`;
|
|
3155
|
+
context.beginPath();
|
|
3156
|
+
roundRectPath(context, bgX, bgY, bgW, bgH, firstBg.borderRadius);
|
|
3157
|
+
context.fill();
|
|
3158
|
+
}
|
|
3131
3159
|
context.restore();
|
|
3132
3160
|
bgIdx = nextIdx;
|
|
3133
3161
|
}
|
|
@@ -3424,8 +3452,8 @@ function computePathBounds2(d) {
|
|
|
3424
3452
|
};
|
|
3425
3453
|
}
|
|
3426
3454
|
function roundRectPath(ctx, x, y, w, h, r) {
|
|
3427
|
-
const maxRadius = Math.min(w, h) / 2;
|
|
3428
|
-
const radius = Math.min(r, maxRadius);
|
|
3455
|
+
const maxRadius = Math.max(0, Math.min(w, h) / 2);
|
|
3456
|
+
const radius = Math.max(0, Math.min(r, maxRadius));
|
|
3429
3457
|
ctx.moveTo(x + radius, y);
|
|
3430
3458
|
ctx.arcTo(x + w, y, x + w, y + h, radius);
|
|
3431
3459
|
ctx.arcTo(x + w, y + h, x, y + h, radius);
|
package/dist/entry.web.js
CHANGED
|
@@ -33483,8 +33483,8 @@ async function buildDrawOps(p) {
|
|
|
33483
33483
|
const canvasCenterY = p.canvas.height / 2;
|
|
33484
33484
|
const bgX = canvasCenterX - contentWidth / 2;
|
|
33485
33485
|
const bgY = canvasCenterY - contentHeight / 2;
|
|
33486
|
-
const maxRadius = Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2;
|
|
33487
|
-
const outerRadius = Math.min(borderRadius, maxRadius);
|
|
33486
|
+
const maxRadius = Math.max(0, Math.min(contentWidth - borderWidth2, contentHeight - borderWidth2) / 2);
|
|
33487
|
+
const outerRadius = Math.max(0, Math.min(borderRadius, maxRadius));
|
|
33488
33488
|
const innerRadius = Math.max(0, outerRadius - halfBorder);
|
|
33489
33489
|
if (p.background?.color) {
|
|
33490
33490
|
ops.push({
|
|
@@ -34359,7 +34359,8 @@ function calculatePopState(ctx, activeScale, speed) {
|
|
|
34359
34359
|
return {
|
|
34360
34360
|
scale: 0.5,
|
|
34361
34361
|
opacity: 0,
|
|
34362
|
-
isActive: false
|
|
34362
|
+
isActive: false,
|
|
34363
|
+
fillProgress: 0
|
|
34363
34364
|
};
|
|
34364
34365
|
}
|
|
34365
34366
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
@@ -34367,28 +34368,33 @@ function calculatePopState(ctx, activeScale, speed) {
|
|
|
34367
34368
|
const progress = calculateAnimationProgress(adjustedCtx);
|
|
34368
34369
|
const easedProgress = easeOutBack(progress);
|
|
34369
34370
|
const startScale = 0.5;
|
|
34370
|
-
const
|
|
34371
|
+
const isActive = isWordActive(ctx);
|
|
34372
|
+
const endScale = isActive ? activeScale : 1;
|
|
34371
34373
|
const scale = startScale + (endScale - startScale) * easedProgress;
|
|
34372
34374
|
return {
|
|
34373
34375
|
scale: Math.min(scale, activeScale),
|
|
34374
34376
|
opacity: easedProgress,
|
|
34375
|
-
isActive
|
|
34377
|
+
isActive,
|
|
34378
|
+
fillProgress: isActive ? 1 : 0
|
|
34376
34379
|
};
|
|
34377
34380
|
}
|
|
34378
34381
|
function calculateFadeState(ctx, speed) {
|
|
34379
34382
|
if (ctx.currentTime < ctx.wordStart) {
|
|
34380
34383
|
return {
|
|
34381
34384
|
opacity: 0,
|
|
34382
|
-
isActive: false
|
|
34385
|
+
isActive: false,
|
|
34386
|
+
fillProgress: 0
|
|
34383
34387
|
};
|
|
34384
34388
|
}
|
|
34385
34389
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
34386
34390
|
const adjustedCtx = { ...ctx, animationDuration: adjustedDuration };
|
|
34387
34391
|
const progress = calculateAnimationProgress(adjustedCtx);
|
|
34388
34392
|
const easedProgress = easeInOutQuad(progress);
|
|
34393
|
+
const isActive = isWordActive(ctx);
|
|
34389
34394
|
return {
|
|
34390
34395
|
opacity: easedProgress,
|
|
34391
|
-
isActive
|
|
34396
|
+
isActive,
|
|
34397
|
+
fillProgress: isActive ? 1 : 0
|
|
34392
34398
|
};
|
|
34393
34399
|
}
|
|
34394
34400
|
function calculateSlideState(ctx, direction, speed, fontSize) {
|
|
@@ -34399,7 +34405,8 @@ function calculateSlideState(ctx, direction, speed, fontSize) {
|
|
|
34399
34405
|
translateX: offset2.x,
|
|
34400
34406
|
translateY: offset2.y,
|
|
34401
34407
|
opacity: 0,
|
|
34402
|
-
isActive: false
|
|
34408
|
+
isActive: false,
|
|
34409
|
+
fillProgress: 0
|
|
34403
34410
|
};
|
|
34404
34411
|
}
|
|
34405
34412
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
@@ -34409,11 +34416,13 @@ function calculateSlideState(ctx, direction, speed, fontSize) {
|
|
|
34409
34416
|
const offset = getDirectionOffset(direction, slideDistance);
|
|
34410
34417
|
const translateX = offset.x * (1 - easedProgress);
|
|
34411
34418
|
const translateY = offset.y * (1 - easedProgress);
|
|
34419
|
+
const isActive = isWordActive(ctx);
|
|
34412
34420
|
return {
|
|
34413
34421
|
translateX,
|
|
34414
34422
|
translateY,
|
|
34415
34423
|
opacity: easeOutQuad2(progress),
|
|
34416
|
-
isActive
|
|
34424
|
+
isActive,
|
|
34425
|
+
fillProgress: isActive ? 1 : 0
|
|
34417
34426
|
};
|
|
34418
34427
|
}
|
|
34419
34428
|
function getDirectionOffset(direction, distance) {
|
|
@@ -34434,17 +34443,20 @@ function calculateBounceState(ctx, speed, fontSize) {
|
|
|
34434
34443
|
return {
|
|
34435
34444
|
translateY: -bounceDistance,
|
|
34436
34445
|
opacity: 0,
|
|
34437
|
-
isActive: false
|
|
34446
|
+
isActive: false,
|
|
34447
|
+
fillProgress: 0
|
|
34438
34448
|
};
|
|
34439
34449
|
}
|
|
34440
34450
|
const adjustedDuration = ctx.animationDuration / speed;
|
|
34441
34451
|
const adjustedCtx = { ...ctx, animationDuration: adjustedDuration };
|
|
34442
34452
|
const progress = calculateAnimationProgress(adjustedCtx);
|
|
34443
34453
|
const easedProgress = easeOutBounce(progress);
|
|
34454
|
+
const isActive = isWordActive(ctx);
|
|
34444
34455
|
return {
|
|
34445
34456
|
translateY: -bounceDistance * (1 - easedProgress),
|
|
34446
34457
|
opacity: easeOutQuad2(progress),
|
|
34447
|
-
isActive
|
|
34458
|
+
isActive,
|
|
34459
|
+
fillProgress: isActive ? 1 : 0
|
|
34448
34460
|
};
|
|
34449
34461
|
}
|
|
34450
34462
|
function calculateTypewriterState(ctx, charCount, speed) {
|
|
@@ -34560,20 +34572,30 @@ var WORD_BG_PADDING_RATIO = 0.12;
|
|
|
34560
34572
|
function extractFontConfig(asset) {
|
|
34561
34573
|
const font = asset.font;
|
|
34562
34574
|
const active = asset.active?.font;
|
|
34575
|
+
const hasActiveConfig = asset.active !== void 0;
|
|
34563
34576
|
const baseColor = font?.color ?? "#ffffff";
|
|
34564
|
-
const
|
|
34565
|
-
|
|
34566
|
-
|
|
34567
|
-
|
|
34568
|
-
|
|
34577
|
+
const baseOpacity = font?.opacity ?? 1;
|
|
34578
|
+
let activeColor;
|
|
34579
|
+
let activeOpacity;
|
|
34580
|
+
if (!hasActiveConfig) {
|
|
34581
|
+
activeColor = baseColor;
|
|
34582
|
+
activeOpacity = baseOpacity;
|
|
34583
|
+
} else {
|
|
34584
|
+
const explicitActiveColor = active?.color;
|
|
34585
|
+
const animStyle = asset.wordAnimation?.style ?? "highlight";
|
|
34586
|
+
const isFillAnimation = animStyle === "karaoke" || animStyle === "highlight";
|
|
34587
|
+
const DEFAULT_ACTIVE_COLOR = "#ffff00";
|
|
34588
|
+
activeColor = explicitActiveColor ?? (isFillAnimation ? DEFAULT_ACTIVE_COLOR : baseColor);
|
|
34589
|
+
activeOpacity = active?.opacity ?? baseOpacity;
|
|
34590
|
+
}
|
|
34569
34591
|
return {
|
|
34570
34592
|
family: font?.family ?? "Roboto",
|
|
34571
34593
|
size: font?.size ?? 24,
|
|
34572
34594
|
weight: String(font?.weight ?? "400"),
|
|
34573
34595
|
baseColor,
|
|
34574
34596
|
activeColor,
|
|
34575
|
-
baseOpacity
|
|
34576
|
-
activeOpacity
|
|
34597
|
+
baseOpacity,
|
|
34598
|
+
activeOpacity,
|
|
34577
34599
|
letterSpacing: asset.style?.letterSpacing ?? 0
|
|
34578
34600
|
};
|
|
34579
34601
|
}
|
|
@@ -34937,8 +34959,8 @@ function createWebPainter(canvas) {
|
|
|
34937
34959
|
const y2 = op.y;
|
|
34938
34960
|
const w = op.width;
|
|
34939
34961
|
const h = op.height;
|
|
34940
|
-
const maxRadius = Math.min(w, h) / 2;
|
|
34941
|
-
const r = Math.min(op.borderRadius, maxRadius);
|
|
34962
|
+
const maxRadius = Math.max(0, Math.min(w, h) / 2);
|
|
34963
|
+
const r = Math.max(0, Math.min(op.borderRadius, maxRadius));
|
|
34942
34964
|
p.moveTo(x2 + r, y2);
|
|
34943
34965
|
p.arcTo(x2 + w, y2, x2 + w, y2 + h, r);
|
|
34944
34966
|
p.arcTo(x2 + w, y2 + h, x2, y2 + h, r);
|
|
@@ -35043,9 +35065,14 @@ function createWebPainter(canvas) {
|
|
|
35043
35065
|
captionWordOps.push(nextOp);
|
|
35044
35066
|
i++;
|
|
35045
35067
|
}
|
|
35068
|
+
const bgSortedOps = [...captionWordOps].sort((a, b) => {
|
|
35069
|
+
const dy = Math.round(a.y) - Math.round(b.y);
|
|
35070
|
+
if (dy !== 0) return dy;
|
|
35071
|
+
return a.x + a.transform.translateX - (b.x + b.transform.translateX);
|
|
35072
|
+
});
|
|
35046
35073
|
let bgIdx = 0;
|
|
35047
|
-
while (bgIdx <
|
|
35048
|
-
const wordOp =
|
|
35074
|
+
while (bgIdx < bgSortedOps.length) {
|
|
35075
|
+
const wordOp = bgSortedOps[bgIdx];
|
|
35049
35076
|
if (!wordOp.background) {
|
|
35050
35077
|
bgIdx++;
|
|
35051
35078
|
continue;
|
|
@@ -35057,13 +35084,12 @@ function createWebPainter(canvas) {
|
|
|
35057
35084
|
}
|
|
35058
35085
|
const mergeGroup = [wordOp];
|
|
35059
35086
|
let nextIdx = bgIdx + 1;
|
|
35060
|
-
while (nextIdx <
|
|
35061
|
-
const nextWord =
|
|
35087
|
+
while (nextIdx < bgSortedOps.length) {
|
|
35088
|
+
const nextWord = bgSortedOps[nextIdx];
|
|
35062
35089
|
if (!nextWord.background) break;
|
|
35063
35090
|
const nextDisplay = getVisibleText(nextWord.text, nextWord.visibleCharacters, nextWord.isRTL);
|
|
35064
35091
|
if (nextDisplay.length === 0) break;
|
|
35065
35092
|
if (Math.round(nextWord.y) !== Math.round(wordOp.y)) break;
|
|
35066
|
-
if (nextWord.background.color !== wordOp.background.color) break;
|
|
35067
35093
|
mergeGroup.push(nextWord);
|
|
35068
35094
|
nextIdx++;
|
|
35069
35095
|
}
|
|
@@ -35091,9 +35117,11 @@ function createWebPainter(canvas) {
|
|
|
35091
35117
|
const bgY = -bgAscent - firstBg.padding;
|
|
35092
35118
|
const bgW = mergedWidth + firstBg.padding * 2;
|
|
35093
35119
|
const bgH = bgTextHeight + firstBg.padding * 2;
|
|
35094
|
-
|
|
35095
|
-
|
|
35096
|
-
|
|
35120
|
+
if (bgW > 0 && bgH > 0) {
|
|
35121
|
+
const bgC = parseHex6(firstBg.color, firstBg.opacity);
|
|
35122
|
+
ctx.fillStyle = `rgba(${bgC.r},${bgC.g},${bgC.b},${bgC.a})`;
|
|
35123
|
+
drawRoundedRect(ctx, bgX, bgY, bgW, bgH, firstBg.borderRadius);
|
|
35124
|
+
}
|
|
35097
35125
|
ctx.restore();
|
|
35098
35126
|
bgIdx = nextIdx;
|
|
35099
35127
|
}
|
|
@@ -35195,8 +35223,8 @@ function createWebPainter(canvas) {
|
|
|
35195
35223
|
};
|
|
35196
35224
|
}
|
|
35197
35225
|
function drawRoundedRect(ctx, x2, y2, w, h, r) {
|
|
35198
|
-
const maxRadius = Math.min(w, h) / 2;
|
|
35199
|
-
const radius = Math.min(r, maxRadius);
|
|
35226
|
+
const maxRadius = Math.max(0, Math.min(w, h) / 2);
|
|
35227
|
+
const radius = Math.max(0, Math.min(r, maxRadius));
|
|
35200
35228
|
const p = new Path2D();
|
|
35201
35229
|
p.moveTo(x2 + radius, y2);
|
|
35202
35230
|
p.arcTo(x2 + w, y2, x2 + w, y2 + h, radius);
|
package/package.json
CHANGED