animot-presenter 0.2.5 → 0.2.6
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/AnimotPresenter.svelte +68 -24
- package/dist/cdn/animot-presenter.esm.js +3932 -3913
- package/dist/cdn/animot-presenter.min.js +8 -8
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
|
@@ -111,6 +111,22 @@
|
|
|
111
111
|
return { x: points[0].x, y: points[0].y, angle: 0 };
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
function computeMotionPathPosition(
|
|
115
|
+
mpPoint: { x: number; y: number; angle: number },
|
|
116
|
+
startPoint: { x: number; y: number; angle: number },
|
|
117
|
+
animX: number, animY: number, animW: number, animH: number
|
|
118
|
+
): { x: number; y: number } {
|
|
119
|
+
const offsetX = (animX + animW / 2) - startPoint.x;
|
|
120
|
+
const offsetY = (animY + animH / 2) - startPoint.y;
|
|
121
|
+
const angleDelta = (mpPoint.angle - startPoint.angle) * Math.PI / 180;
|
|
122
|
+
const cos = Math.cos(angleDelta);
|
|
123
|
+
const sin = Math.sin(angleDelta);
|
|
124
|
+
return {
|
|
125
|
+
x: mpPoint.x + offsetX * cos - offsetY * sin - animW / 2,
|
|
126
|
+
y: mpPoint.y + offsetX * sin + offsetY * cos - animH / 2
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
114
130
|
let {
|
|
115
131
|
src, data, autoplay = false, loop = false, controls = true, arrows = false,
|
|
116
132
|
progress: showProgress = true, keyboard = true, duration: durationOverride,
|
|
@@ -316,7 +332,7 @@
|
|
|
316
332
|
for (const element of slide.canvas.elements) {
|
|
317
333
|
if (!animatedElements.has(element.id)) {
|
|
318
334
|
const inCurrent = getElementInSlide(currentSlide, element.id);
|
|
319
|
-
const startOpacity = inCurrent ? 1 : 0;
|
|
335
|
+
const startOpacity = inCurrent ? ((inCurrent as any).opacity ?? 1) : 0;
|
|
320
336
|
const br = (element as any).borderRadius ?? 0;
|
|
321
337
|
const isShape = element.type === 'shape';
|
|
322
338
|
const shapeEl = isShape ? element as ShapeElement : null;
|
|
@@ -382,11 +398,14 @@
|
|
|
382
398
|
const shouldLoop = element.motionPathConfig.loop;
|
|
383
399
|
|
|
384
400
|
if (shouldLoop) {
|
|
401
|
+
const laps = element.motionPathConfig.laps ?? 0;
|
|
385
402
|
(async () => {
|
|
386
|
-
|
|
403
|
+
let lap = 0;
|
|
404
|
+
while (!signal.aborted && (laps === 0 || lap < laps)) {
|
|
387
405
|
await animated.motionPathProgress!.to(0, { duration: 0 });
|
|
388
406
|
await animated.motionPathProgress!.to(1, { duration, easing });
|
|
389
|
-
|
|
407
|
+
lap++;
|
|
408
|
+
if (!signal.aborted && (laps === 0 || lap < laps)) await new Promise(r => setTimeout(r, 50));
|
|
390
409
|
}
|
|
391
410
|
})();
|
|
392
411
|
} else {
|
|
@@ -435,7 +454,7 @@
|
|
|
435
454
|
animated.skewX.to(targetEl.skewX ?? 0, { duration: 0 }); animated.skewY.to(targetEl.skewY ?? 0, { duration: 0 });
|
|
436
455
|
animated.tiltX.to(targetEl.tiltX ?? 0, { duration: 0 }); animated.tiltY.to(targetEl.tiltY ?? 0, { duration: 0 });
|
|
437
456
|
animated.perspective.to(targetEl.perspective ?? 1000, { duration: 0 });
|
|
438
|
-
animated.opacity.to(1, { duration: 0 });
|
|
457
|
+
animated.opacity.to((targetEl as any).opacity ?? 1, { duration: 0 });
|
|
439
458
|
animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: 0 });
|
|
440
459
|
animated.blur.to(targetEl.blur ?? 0, { duration: 0 });
|
|
441
460
|
animated.brightness.to(targetEl.brightness ?? 100, { duration: 0 });
|
|
@@ -510,7 +529,7 @@
|
|
|
510
529
|
await animated.contrast.to(currentEl.contrast ?? 100, { duration: 0 });
|
|
511
530
|
await animated.saturate.to(currentEl.saturate ?? 100, { duration: 0 });
|
|
512
531
|
await animated.grayscale.to(currentEl.grayscale ?? 0, { duration: 0 });
|
|
513
|
-
await animated.opacity.to(1, { duration: 0 });
|
|
532
|
+
await animated.opacity.to((currentEl as any).opacity ?? 1, { duration: 0 });
|
|
514
533
|
if (currentEl.type === 'text' && animated.fontSize) await animated.fontSize.to((currentEl as TextElement).fontSize, { duration: 0 });
|
|
515
534
|
if (currentEl.type === 'shape') {
|
|
516
535
|
const s = currentEl as ShapeElement;
|
|
@@ -578,6 +597,10 @@
|
|
|
578
597
|
animated.grayscale.to(targetEl.grayscale ?? 0, { duration: elementDuration, easing });
|
|
579
598
|
}
|
|
580
599
|
if (!sequencedProps.has('perspective')) anims.push(animated.perspective.to(targetEl.perspective ?? 1000, { duration: elementDuration, easing }));
|
|
600
|
+
if (!sequencedProps.has('opacity')) {
|
|
601
|
+
const targetOpacity = (targetEl as any).opacity ?? 1;
|
|
602
|
+
if (animated.opacity.current !== targetOpacity) anims.push(animated.opacity.to(targetOpacity, { duration: elementDuration, easing }));
|
|
603
|
+
}
|
|
581
604
|
const sortedSeqs = [...propertySequences].sort((a, b) => a.order - b.order);
|
|
582
605
|
let cumulativeDelay = 0;
|
|
583
606
|
for (const seq of sortedSeqs) {
|
|
@@ -604,6 +627,7 @@
|
|
|
604
627
|
animated.strokeWidth?.to(s.strokeWidth, { duration: seqDuration, easing });
|
|
605
628
|
}
|
|
606
629
|
else if (seq.property === 'perspective') animated.perspective.to(targetEl.perspective ?? 1000, { duration: seqDuration, easing });
|
|
630
|
+
else if (seq.property === 'opacity') animated.opacity.to((targetEl as any).opacity ?? 1, { duration: seqDuration, easing });
|
|
607
631
|
}, seqDelay);
|
|
608
632
|
cumulativeDelay = seqDelay + seqDuration;
|
|
609
633
|
}
|
|
@@ -625,6 +649,12 @@
|
|
|
625
649
|
anims.push(animated.contrast.to(targetEl.contrast ?? 100, { duration: elementDuration, easing }));
|
|
626
650
|
anims.push(animated.saturate.to(targetEl.saturate ?? 100, { duration: elementDuration, easing }));
|
|
627
651
|
anims.push(animated.grayscale.to(targetEl.grayscale ?? 0, { duration: elementDuration, easing }));
|
|
652
|
+
// Opacity interpolation for morphing elements
|
|
653
|
+
const currOpacity = animated.opacity.current;
|
|
654
|
+
const targetOpacity = (targetEl as any).opacity ?? 1;
|
|
655
|
+
if (currOpacity !== targetOpacity) {
|
|
656
|
+
anims.push(animated.opacity.to(targetOpacity, { duration: elementDuration, easing }));
|
|
657
|
+
}
|
|
628
658
|
}
|
|
629
659
|
// Motion path progress — await reset, then animate forward
|
|
630
660
|
if (animated.motionPathProgress && targetEl.motionPathConfig) {
|
|
@@ -686,10 +716,11 @@
|
|
|
686
716
|
if (animated.strokeWidth) anims.push(animated.strokeWidth.to(s.strokeWidth, { duration: 0 }));
|
|
687
717
|
}
|
|
688
718
|
const entrance = targetEl.animationConfig?.entrance ?? 'fade';
|
|
719
|
+
const targetOpacity = (targetEl as any).opacity ?? 1;
|
|
689
720
|
if (entrance === 'fade') {
|
|
690
|
-
anims.push(animated.opacity.to(
|
|
721
|
+
anims.push(animated.opacity.to(targetOpacity, { duration: elementDuration / 2, easing }));
|
|
691
722
|
} else {
|
|
692
|
-
anims.push(animated.opacity.to(
|
|
723
|
+
anims.push(animated.opacity.to(targetOpacity, { duration: 0 }));
|
|
693
724
|
}
|
|
694
725
|
}
|
|
695
726
|
return anims;
|
|
@@ -985,8 +1016,14 @@
|
|
|
985
1016
|
{@const mpElement = mpConfig ? currentSlide?.canvas.elements.find(el => el.id === mpConfig.motionPathId) as MotionPathElement | undefined : undefined}
|
|
986
1017
|
{@const mpProgress = animated?.motionPathProgress?.current ?? 0}
|
|
987
1018
|
{@const mpPoint = mpElement && mpConfig ? getPresenterPointOnPath(mpElement.points, mpElement.closed, (mpConfig.startPercent + (mpConfig.endPercent - mpConfig.startPercent) * mpProgress) / 100) : null}
|
|
988
|
-
{@const
|
|
989
|
-
{@const
|
|
1019
|
+
{@const mpStartPoint = mpElement && mpConfig ? getPresenterPointOnPath(mpElement.points, mpElement.closed, mpConfig.startPercent / 100) : null}
|
|
1020
|
+
{@const mpPos = mpPoint && mpStartPoint && animated
|
|
1021
|
+
? computeMotionPathPosition(mpPoint, mpStartPoint,
|
|
1022
|
+
animated.x.current, animated.y.current,
|
|
1023
|
+
animated.width.current, animated.height.current)
|
|
1024
|
+
: null}
|
|
1025
|
+
{@const elemX = mpPos ? mpPos.x : (animated?.x.current ?? 0)}
|
|
1026
|
+
{@const elemY = mpPos ? mpPos.y : (animated?.y.current ?? 0)}
|
|
990
1027
|
{@const mpRotation = mpPoint && mpConfig?.autoRotate
|
|
991
1028
|
? mpPoint.angle + (mpConfig.orientationOffset ?? 0)
|
|
992
1029
|
: null}
|
|
@@ -1089,7 +1126,6 @@
|
|
|
1089
1126
|
style:border-radius="{textEl.borderRadius}px"
|
|
1090
1127
|
style:text-align={textEl.textAlign}
|
|
1091
1128
|
style:justify-content={textEl.textAlign === 'center' ? 'center' : textEl.textAlign === 'right' ? 'flex-end' : 'flex-start'}
|
|
1092
|
-
style:opacity={textEl.opacity ?? 1}
|
|
1093
1129
|
style:-webkit-text-stroke={textEl.textStroke?.enabled ? `${textEl.textStroke.width}px ${textEl.textStroke.color}` : '0'}
|
|
1094
1130
|
style:text-shadow={textEl.textShadow?.enabled ? `${textEl.textShadow.offsetX}px ${textEl.textShadow.offsetY}px ${textEl.textShadow.blur}px ${textEl.textShadow.color}` : 'none'}
|
|
1095
1131
|
>
|
|
@@ -1118,7 +1154,7 @@
|
|
|
1118
1154
|
{:else if element.type === 'image'}
|
|
1119
1155
|
{@const imgEl = element as ImageElement}
|
|
1120
1156
|
{@const clipPath = imgEl.clipMask?.enabled ? (imgEl.clipMask.shapeType === 'circle' ? 'circle(50% at 50% 50%)' : imgEl.clipMask.shapeType === 'ellipse' ? 'ellipse(50% 50% at 50% 50%)' : imgEl.clipMask.shapeType === 'triangle' ? 'polygon(50% 0%, 0% 100%, 100% 100%)' : imgEl.clipMask.shapeType === 'star' ? 'polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)' : imgEl.clipMask.shapeType === 'hexagon' ? 'polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)' : (imgEl.clipMask.borderRadius ?? 0) > 0 ? `inset(0 round ${imgEl.clipMask.borderRadius}px)` : 'none') : 'none'}
|
|
1121
|
-
<img class="animot-image-element" src={imgEl.src} alt="" style:object-fit={imgEl.objectFit} style:border-radius="{imgEl.clipMask?.enabled ? 0 : imgEl.borderRadius}px" style:
|
|
1157
|
+
<img class="animot-image-element" src={imgEl.src} alt="" style:object-fit={imgEl.objectFit} style:border-radius="{imgEl.clipMask?.enabled ? 0 : imgEl.borderRadius}px" style:clip-path={clipPath} style:background-color={imgEl.backgroundColor ?? 'transparent'} />
|
|
1122
1158
|
{:else if element.type === 'shape'}
|
|
1123
1159
|
{@const shapeEl = element as ShapeElement}
|
|
1124
1160
|
{@const animFill = animated.fillColor?.current ?? shapeEl.fillColor}
|
|
@@ -1128,15 +1164,15 @@
|
|
|
1128
1164
|
{@const morphProgress = animated.shapeMorph?.current ?? 1}
|
|
1129
1165
|
{@const effectiveShapeType = mState ? (morphProgress >= 1 ? mState.toType : (morphProgress <= 0 ? mState.fromType : null)) : shapeEl.shapeType}
|
|
1130
1166
|
{@const isMorphing = mState && morphProgress > 0 && morphProgress < 1}
|
|
1131
|
-
<svg class="animot-shape-element" viewBox="0 0 {animated.width.current} {animated.height.current}" style:
|
|
1167
|
+
<svg class="animot-shape-element" viewBox="0 0 {animated.width.current} {animated.height.current}" style:filter={shapeEl.boxShadow?.enabled ? `drop-shadow(${shapeEl.boxShadow.offsetX}px ${shapeEl.boxShadow.offsetY}px ${shapeEl.boxShadow.blur}px ${shapeEl.boxShadow.color})` : 'none'}>
|
|
1132
1168
|
{#if isMorphing}
|
|
1133
1169
|
{@const w = animated.width.current}
|
|
1134
1170
|
{@const h = animated.height.current}
|
|
1135
1171
|
{@const sw = animStrokeWidth}
|
|
1136
|
-
<g style:opacity={1 - morphProgress}>{@html renderShape(mState!.fromType, w, h, animated.borderRadius.current, animFill, animStroke, sw)}</g>
|
|
1137
|
-
<g style:opacity={morphProgress}>{@html renderShape(mState!.toType, w, h, animated.borderRadius.current, animFill, animStroke, sw)}</g>
|
|
1172
|
+
<g style:opacity={1 - morphProgress}>{@html renderShape(mState!.fromType, w, h, animated.borderRadius.current, animFill, animStroke, sw, shapeEl.strokeStyle, shapeEl.strokeDashGap)}</g>
|
|
1173
|
+
<g style:opacity={morphProgress}>{@html renderShape(mState!.toType, w, h, animated.borderRadius.current, animFill, animStroke, sw, shapeEl.strokeStyle, shapeEl.strokeDashGap)}</g>
|
|
1138
1174
|
{:else}
|
|
1139
|
-
{@html renderShape(effectiveShapeType ?? shapeEl.shapeType, animated.width.current, animated.height.current, animated.borderRadius.current, animFill, animStroke, animStrokeWidth)}
|
|
1175
|
+
{@html renderShape(effectiveShapeType ?? shapeEl.shapeType, animated.width.current, animated.height.current, animated.borderRadius.current, animFill, animStroke, animStrokeWidth, shapeEl.strokeStyle, shapeEl.strokeDashGap)}
|
|
1140
1176
|
{/if}
|
|
1141
1177
|
</svg>
|
|
1142
1178
|
{:else if element.type === 'counter'}
|
|
@@ -1148,7 +1184,7 @@
|
|
|
1148
1184
|
{:else if element.type === 'svg'}
|
|
1149
1185
|
{@const svgEl = element as SvgElement}
|
|
1150
1186
|
{@const svgParsed = (() => { const m = svgEl.svgContent.trim().match(/^<svg([^>]*)>([\s\S]*)<\/svg>$/i); if (m) { const vb = m[1].match(/viewBox=["']([^"']+)["']/i); return { inner: m[2], viewBox: vb ? vb[1] : null }; } return { inner: svgEl.svgContent, viewBox: null }; })()}
|
|
1151
|
-
<div class="animot-svg-element"
|
|
1187
|
+
<div class="animot-svg-element">
|
|
1152
1188
|
<svg width="100%" height="100%" viewBox={svgEl.viewBox ?? svgParsed.viewBox ?? `0 0 ${svgEl.size.width} ${svgEl.size.height}`} preserveAspectRatio={svgEl.preserveAspectRatio} xmlns="http://www.w3.org/2000/svg">
|
|
1153
1189
|
<g style={svgEl.color ? `fill:${svgEl.color};stroke:${svgEl.color}` : ''}>
|
|
1154
1190
|
{@html svgParsed.inner}
|
|
@@ -1158,7 +1194,7 @@
|
|
|
1158
1194
|
{:else if element.type === 'motionPath'}
|
|
1159
1195
|
{@const mpEl = element as MotionPathElement}
|
|
1160
1196
|
{#if mpEl.showInPresentation}
|
|
1161
|
-
<svg width="100%" height="100%" style="position:absolute;top:0;left:0;pointer-events:none;overflow:visible;">
|
|
1197
|
+
<svg width="100%" height="100%" viewBox="0 0 {animated.width.current} {animated.height.current}" style="position:absolute;top:0;left:0;pointer-events:none;overflow:visible;">
|
|
1162
1198
|
<path d={buildPresenterPathD(mpEl.points, mpEl.closed)} stroke={mpEl.pathColor} stroke-width={mpEl.pathWidth} fill="none" stroke-dasharray="8 4" />
|
|
1163
1199
|
</svg>
|
|
1164
1200
|
{/if}
|
|
@@ -1204,21 +1240,29 @@
|
|
|
1204
1240
|
</div>
|
|
1205
1241
|
|
|
1206
1242
|
<script module lang="ts">
|
|
1207
|
-
function renderShape(type: string, w: number, h: number, br: number, fill: string, stroke: string, sw: number): string {
|
|
1243
|
+
function renderShape(type: string, w: number, h: number, br: number, fill: string, stroke: string, sw: number, strokeStyle?: string, strokeDashGap?: number): string {
|
|
1244
|
+
let dashAttr = '';
|
|
1245
|
+
if (strokeStyle && strokeStyle !== 'solid') {
|
|
1246
|
+
const s = sw || 1;
|
|
1247
|
+
const gap = strokeDashGap ?? (strokeStyle === 'dashed' ? s * 3 : s * 2);
|
|
1248
|
+
const da = strokeStyle === 'dashed' ? `${s * 3},${gap}` : `${s * 0.1},${gap}`;
|
|
1249
|
+
const lc = strokeStyle === 'dotted' ? 'round' : 'butt';
|
|
1250
|
+
dashAttr = ` stroke-dasharray="${da}" stroke-linecap="${lc}"`;
|
|
1251
|
+
}
|
|
1208
1252
|
switch (type) {
|
|
1209
|
-
case 'rectangle': return `<rect x="${sw/2}" y="${sw/2}" width="${w-sw}" height="${h-sw}" rx="${br}" ry="${br}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}"/>`;
|
|
1210
|
-
case 'circle': return `<circle cx="${w/2}" cy="${h/2}" r="${Math.min(w,h)/2-sw/2}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}"/>`;
|
|
1211
|
-
case 'ellipse': return `<ellipse cx="${w/2}" cy="${h/2}" rx="${w/2-sw/2}" ry="${h/2-sw/2}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}"/>`;
|
|
1212
|
-
case 'triangle': return `<polygon points="${w/2},${sw/2} ${sw/2},${h-sw/2} ${w-sw/2},${h-sw/2}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}" stroke-linejoin="round"/>`;
|
|
1253
|
+
case 'rectangle': return `<rect x="${sw/2}" y="${sw/2}" width="${w-sw}" height="${h-sw}" rx="${br}" ry="${br}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}"${dashAttr}/>`;
|
|
1254
|
+
case 'circle': return `<circle cx="${w/2}" cy="${h/2}" r="${Math.min(w,h)/2-sw/2}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}"${dashAttr}/>`;
|
|
1255
|
+
case 'ellipse': return `<ellipse cx="${w/2}" cy="${h/2}" rx="${w/2-sw/2}" ry="${h/2-sw/2}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}"${dashAttr}/>`;
|
|
1256
|
+
case 'triangle': return `<polygon points="${w/2},${sw/2} ${sw/2},${h-sw/2} ${w-sw/2},${h-sw/2}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}"${dashAttr} stroke-linejoin="round"/>`;
|
|
1213
1257
|
case 'star': {
|
|
1214
1258
|
const cx = w/2, cy = h/2, outerR = Math.min(w,h)/2-sw/2, innerR = outerR*0.4;
|
|
1215
1259
|
const pts = Array.from({length:10},(_,i)=>{const a=(i*Math.PI/5)-Math.PI/2;const r=i%2===0?outerR:innerR;return`${cx+r*Math.cos(a)},${cy+r*Math.sin(a)}`;}).join(' ');
|
|
1216
|
-
return `<polygon points="${pts}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}" stroke-linejoin="round"/>`;
|
|
1260
|
+
return `<polygon points="${pts}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}"${dashAttr} stroke-linejoin="round"/>`;
|
|
1217
1261
|
}
|
|
1218
1262
|
case 'hexagon': {
|
|
1219
1263
|
const cx = w/2, cy = h/2, r = Math.min(w,h)/2-sw/2;
|
|
1220
1264
|
const pts = Array.from({length:6},(_,i)=>{const a=(i*Math.PI/3)-Math.PI/2;return`${cx+r*Math.cos(a)},${cy+r*Math.sin(a)}`;}).join(' ');
|
|
1221
|
-
return `<polygon points="${pts}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}" stroke-linejoin="round"/>`;
|
|
1265
|
+
return `<polygon points="${pts}" fill="${fill}" stroke="${stroke}" stroke-width="${sw}"${dashAttr} stroke-linejoin="round"/>`;
|
|
1222
1266
|
}
|
|
1223
1267
|
default: return '';
|
|
1224
1268
|
}
|