@versa_ai/vmml-editor 1.0.38 → 1.0.40
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/.turbo/turbo-build.log +8 -8
- package/dist/index.js +174 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/components/EditorCanvas.tsx +252 -90
- package/src/utils/VmmlConverter.ts +26 -15
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @versa_ai/vmml-editor@1.0.
|
|
2
|
+
> @versa_ai/vmml-editor@1.0.40 build D:\code\work\vmml-player\packages\editor
|
|
3
3
|
> tsup
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.tsx
|
|
@@ -124,12 +124,12 @@ More info and automated migrator: https://sass-lang.com/d/slash-div[0m [1m[35
|
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
[34mDTS[39m Build start
|
|
127
|
-
[32mESM[39m [1mdist\index.mjs [22m[
|
|
128
|
-
[32mESM[39m [1mdist\index.mjs.map [22m[
|
|
129
|
-
[32mESM[39m ⚡️ Build success in
|
|
130
|
-
[32mCJS[39m [1mdist\index.js [22m[
|
|
131
|
-
[32mCJS[39m [1mdist\index.js.map [22m[
|
|
132
|
-
[32mCJS[39m ⚡️ Build success in
|
|
133
|
-
[32mDTS[39m ⚡️ Build success in
|
|
127
|
+
[32mESM[39m [1mdist\index.mjs [22m[32m120.82 KB[39m
|
|
128
|
+
[32mESM[39m [1mdist\index.mjs.map [22m[32m234.06 KB[39m
|
|
129
|
+
[32mESM[39m ⚡️ Build success in 753ms
|
|
130
|
+
[32mCJS[39m [1mdist\index.js [22m[32m122.51 KB[39m
|
|
131
|
+
[32mCJS[39m [1mdist\index.js.map [22m[32m234.35 KB[39m
|
|
132
|
+
[32mCJS[39m ⚡️ Build success in 754ms
|
|
133
|
+
[32mDTS[39m ⚡️ Build success in 2765ms
|
|
134
134
|
[32mDTS[39m [1mdist\index.d.ts [22m[32m158.00 B[39m
|
|
135
135
|
[32mDTS[39m [1mdist\index.d.mts [22m[32m158.00 B[39m
|
package/dist/index.js
CHANGED
|
@@ -709,15 +709,20 @@ var VmmlConverter = class {
|
|
|
709
709
|
* @param fObj - 画布fObj
|
|
710
710
|
*/
|
|
711
711
|
updateClip(fObj) {
|
|
712
|
-
console.log("updateClip fObj", fObj);
|
|
712
|
+
console.log("updateClip fObj", fObj, this.tracks);
|
|
713
713
|
const posParam = this.setPosParam(fObj);
|
|
714
714
|
const {
|
|
715
|
-
// clipData: { id, type, lineSpacing },
|
|
716
715
|
clipData: { id, type, lineSpacing, originClip }
|
|
717
716
|
} = fObj;
|
|
718
717
|
let existClip = null;
|
|
719
718
|
if (originClip) {
|
|
720
|
-
|
|
719
|
+
for (const track of this.tracks) {
|
|
720
|
+
const clip = (track.clips || []).find((c) => c.id === originClip.id);
|
|
721
|
+
if (clip) {
|
|
722
|
+
existClip = clip;
|
|
723
|
+
break;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
721
726
|
} else {
|
|
722
727
|
const editorTrack = this.tracks.find((track) => track.editorType === type);
|
|
723
728
|
existClip = ((editorTrack == null ? void 0 : editorTrack.clips) || []).find((clip) => clip.id === id);
|
|
@@ -742,7 +747,6 @@ var VmmlConverter = class {
|
|
|
742
747
|
};
|
|
743
748
|
}
|
|
744
749
|
}
|
|
745
|
-
console.log("updateClip \u6700\u7EC8vmml", this.vmml);
|
|
746
750
|
}
|
|
747
751
|
/**
|
|
748
752
|
* 删除 Clip
|
|
@@ -751,7 +755,13 @@ var VmmlConverter = class {
|
|
|
751
755
|
*/
|
|
752
756
|
deleteClip({ id, type, originClip }) {
|
|
753
757
|
if (originClip) {
|
|
754
|
-
|
|
758
|
+
for (const track of this.tracks) {
|
|
759
|
+
const clip = (track.clips || []).find((c) => c.id === originClip.id);
|
|
760
|
+
if (clip) {
|
|
761
|
+
clip.duration = 0;
|
|
762
|
+
break;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
755
765
|
} else {
|
|
756
766
|
const editorTrack = this.tracks.find((track) => track.editorType === type);
|
|
757
767
|
const index = editorTrack.clips.findIndex((item) => item.id === id);
|
|
@@ -769,7 +779,9 @@ var VmmlConverter = class {
|
|
|
769
779
|
}
|
|
770
780
|
}
|
|
771
781
|
}
|
|
772
|
-
|
|
782
|
+
}
|
|
783
|
+
changeVmml(newVmml) {
|
|
784
|
+
this.vmml = newVmml;
|
|
773
785
|
}
|
|
774
786
|
//切换静音 视频/音频
|
|
775
787
|
changeMute({ id, isMute }) {
|
|
@@ -1020,6 +1032,7 @@ var EditorCanvas = react.forwardRef(
|
|
|
1020
1032
|
const vmmlConverterRef = react.useRef(null);
|
|
1021
1033
|
const heightScaleRef = react.useRef(1);
|
|
1022
1034
|
const widthScaleRef = react.useRef(1);
|
|
1035
|
+
const fontCacheRef = react.useRef(/* @__PURE__ */ new Map());
|
|
1023
1036
|
const initCanvas = () => {
|
|
1024
1037
|
const canvas = new fabric.fabric.Canvas("canvas", {
|
|
1025
1038
|
width: canvasSize.width,
|
|
@@ -1058,9 +1071,9 @@ var EditorCanvas = react.forwardRef(
|
|
|
1058
1071
|
objects.forEach((item) => {
|
|
1059
1072
|
var _a, _b, _c;
|
|
1060
1073
|
if (((_a = item == null ? void 0 : item.clipData) == null ? void 0 : _a.type) === "\u6587\u5B57") {
|
|
1061
|
-
item.set("visible", ns >= item.clipData.inPoint && ns < item.clipData.inPoint + (item.clipData.duration || vmml.template.duration));
|
|
1074
|
+
item.set("visible", item.clipData.duration > 0 && ns >= item.clipData.inPoint && ns < item.clipData.inPoint + (item.clipData.duration || vmml.template.duration));
|
|
1062
1075
|
} else {
|
|
1063
|
-
item.set("visible", ns >= item.clipData.inPoint && ns < item.clipData.inPoint + ((_c = (_b = item.clipData) == null ? void 0 : _b.fileUrl) == null ? void 0 : _c.duration));
|
|
1076
|
+
item.set("visible", item.clipData.duration > 0 && ns >= item.clipData.inPoint && ns < item.clipData.inPoint + ((_c = (_b = item.clipData) == null ? void 0 : _b.fileUrl) == null ? void 0 : _c.duration));
|
|
1064
1077
|
}
|
|
1065
1078
|
});
|
|
1066
1079
|
fc.discardActiveObject();
|
|
@@ -1213,7 +1226,7 @@ var EditorCanvas = react.forwardRef(
|
|
|
1213
1226
|
return createImageFromClip(clip);
|
|
1214
1227
|
}
|
|
1215
1228
|
if (clip.textClip && !clip.audioClip) {
|
|
1216
|
-
return
|
|
1229
|
+
return createTextFromClipCanvas(clip);
|
|
1217
1230
|
}
|
|
1218
1231
|
});
|
|
1219
1232
|
const res = await Promise.allSettled(promises);
|
|
@@ -1223,6 +1236,7 @@ var EditorCanvas = react.forwardRef(
|
|
|
1223
1236
|
objects.push(item.value);
|
|
1224
1237
|
}
|
|
1225
1238
|
});
|
|
1239
|
+
console.log(editRenderTime.current === time, "editRenderTime.current === time");
|
|
1226
1240
|
if (editRenderTime.current === time) {
|
|
1227
1241
|
canvas.add(...objects).renderAll();
|
|
1228
1242
|
checkObjectInPoint();
|
|
@@ -1311,6 +1325,134 @@ var EditorCanvas = react.forwardRef(
|
|
|
1311
1325
|
});
|
|
1312
1326
|
window.dispatchEvent(event);
|
|
1313
1327
|
};
|
|
1328
|
+
const createTextFromClipCanvas = async (clip, fc2) => {
|
|
1329
|
+
return new Promise(async (resolve) => {
|
|
1330
|
+
const canvas = fc || fc2;
|
|
1331
|
+
if (!canvas) return null;
|
|
1332
|
+
const { width, height } = vmml.template.dimension;
|
|
1333
|
+
const fontSize = vmmlUtils.getFontSize(width, height);
|
|
1334
|
+
const { textContent, backgroundColor, textColor, posParam, fontAssetUrl, alignType, strokeColor, strokeWidth, letterSpacing } = clip.textClip;
|
|
1335
|
+
const scaleX = posParam.scaleX * fontSize / 22 / widthScaleRef.current;
|
|
1336
|
+
const scaleY = posParam.scaleY * fontSize / 22 / heightScaleRef.current;
|
|
1337
|
+
const left = canvasSize.width * posParam.centerX;
|
|
1338
|
+
const top = canvasSize.height * posParam.centerY;
|
|
1339
|
+
const bgColor = backgroundColor ? vmmlUtils.argbToRgba(backgroundColor) : "transparent";
|
|
1340
|
+
const stColor = strokeColor ? vmmlUtils.argbToRgba(strokeColor) : "transparent";
|
|
1341
|
+
const textFill = vmmlUtils.argbToRgba(textColor || "#ffffffff");
|
|
1342
|
+
const strokeW = strokeColor && strokeWidth ? strokeWidth * 26 * 1.5 / fontSize : 0;
|
|
1343
|
+
const letterSpace = letterSpacing * 22 / fontSize;
|
|
1344
|
+
let fontFamily = "sansMedium";
|
|
1345
|
+
if (fontAssetUrl) {
|
|
1346
|
+
const base64 = await loadFont(fontAssetUrl);
|
|
1347
|
+
if (base64) {
|
|
1348
|
+
fontFamily = getFontFamilyName(fontAssetUrl);
|
|
1349
|
+
await document.fonts.ready;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
const lines = textContent.split("\n").filter((item) => item);
|
|
1353
|
+
const lineHeight = 22 + strokeW;
|
|
1354
|
+
const textHeight = lines.length * lineHeight;
|
|
1355
|
+
const groupWidth = Math.max(...lines.map((l) => {
|
|
1356
|
+
const temp = new fabric.fabric.Text(l || " ", { fontSize: 22, fontFamily, charSpacing: (letterSpace || 0) * 50, strokeWidth: strokeW ?? 0 });
|
|
1357
|
+
return (temp == null ? void 0 : temp.width) ?? 0;
|
|
1358
|
+
})) + 14;
|
|
1359
|
+
const groupHeight = textHeight + 13;
|
|
1360
|
+
const textObjs = [];
|
|
1361
|
+
lines.forEach((line, idx) => {
|
|
1362
|
+
const y = (groupHeight - textHeight) / 2 + idx * lineHeight + lineHeight / 2 + 1;
|
|
1363
|
+
const strokeText = new fabric.fabric.Text(line || " ", {
|
|
1364
|
+
fontFamily,
|
|
1365
|
+
fontSize: 22,
|
|
1366
|
+
fill: "transparent",
|
|
1367
|
+
stroke: stColor,
|
|
1368
|
+
strokeWidth: strokeW,
|
|
1369
|
+
originX: "center",
|
|
1370
|
+
originY: "center",
|
|
1371
|
+
left: groupWidth / 2,
|
|
1372
|
+
// 水平居中
|
|
1373
|
+
top: y,
|
|
1374
|
+
charSpacing: (letterSpace || 0) * 50,
|
|
1375
|
+
textAlign: alignType === 1 ? "center" : alignType === 2 ? "right" : "left",
|
|
1376
|
+
objectCaching: false
|
|
1377
|
+
});
|
|
1378
|
+
const fillText = new fabric.fabric.Text(line || " ", {
|
|
1379
|
+
fontFamily,
|
|
1380
|
+
fontSize: 22,
|
|
1381
|
+
fill: textFill,
|
|
1382
|
+
stroke: "transparent",
|
|
1383
|
+
originX: "center",
|
|
1384
|
+
originY: "center",
|
|
1385
|
+
strokeWidth: 0,
|
|
1386
|
+
left: groupWidth / 2,
|
|
1387
|
+
// 水平居中
|
|
1388
|
+
top: y,
|
|
1389
|
+
charSpacing: (letterSpace || 0) * 50,
|
|
1390
|
+
textAlign: alignType === 1 ? "center" : alignType === 2 ? "right" : "left",
|
|
1391
|
+
objectCaching: false
|
|
1392
|
+
});
|
|
1393
|
+
textObjs.push(strokeText, fillText);
|
|
1394
|
+
});
|
|
1395
|
+
const bgRect = new fabric.fabric.Rect({
|
|
1396
|
+
width: groupWidth,
|
|
1397
|
+
height: groupHeight,
|
|
1398
|
+
fill: bgColor,
|
|
1399
|
+
originX: "left",
|
|
1400
|
+
originY: "top",
|
|
1401
|
+
rx: 5,
|
|
1402
|
+
ry: 5,
|
|
1403
|
+
left: 0,
|
|
1404
|
+
top: 0
|
|
1405
|
+
});
|
|
1406
|
+
const textBasicInfo = {
|
|
1407
|
+
isBack: backgroundColor ? true : false,
|
|
1408
|
+
colorValue: textFill,
|
|
1409
|
+
colorName: "custom",
|
|
1410
|
+
textAlign: alignType === 1 ? "center" : alignType === 2 ? "right" : "left"
|
|
1411
|
+
};
|
|
1412
|
+
const group = new fabric.fabric.Group([bgRect, ...textObjs], {
|
|
1413
|
+
left,
|
|
1414
|
+
top,
|
|
1415
|
+
scaleX,
|
|
1416
|
+
scaleY,
|
|
1417
|
+
angle: posParam.rotationZ,
|
|
1418
|
+
originX: "center",
|
|
1419
|
+
originY: "center",
|
|
1420
|
+
clipData: {
|
|
1421
|
+
id: clip.id,
|
|
1422
|
+
inPoint: clip.inPoint,
|
|
1423
|
+
inFrame: vmmlUtils.getFrames(clip.inPoint, 30),
|
|
1424
|
+
type: "\u6587\u5B57",
|
|
1425
|
+
textColor: textFill,
|
|
1426
|
+
text: textContent,
|
|
1427
|
+
bgColor,
|
|
1428
|
+
originClip: clip,
|
|
1429
|
+
fontAssetUrl,
|
|
1430
|
+
fontFamily,
|
|
1431
|
+
textBasicInfo,
|
|
1432
|
+
duration: clip.duration
|
|
1433
|
+
},
|
|
1434
|
+
objectCaching: false
|
|
1435
|
+
});
|
|
1436
|
+
group.on("selected", (options) => {
|
|
1437
|
+
options.target.isSelected = -1;
|
|
1438
|
+
});
|
|
1439
|
+
group.on("moving", (options) => {
|
|
1440
|
+
options.transform.target.isSelected = 0;
|
|
1441
|
+
});
|
|
1442
|
+
group.on("modified", () => {
|
|
1443
|
+
const fObj = convertToJSON(group);
|
|
1444
|
+
if (fObj.clipData.isAiError) {
|
|
1445
|
+
fObj.clipData.textColor = "rgba(0, 0, 0, 0)";
|
|
1446
|
+
}
|
|
1447
|
+
if (isBatchModify) {
|
|
1448
|
+
onBatchModify(fObj, canvas);
|
|
1449
|
+
} else {
|
|
1450
|
+
vmmlConverterRef.current.updateClip(fObj);
|
|
1451
|
+
}
|
|
1452
|
+
});
|
|
1453
|
+
resolve(group);
|
|
1454
|
+
});
|
|
1455
|
+
};
|
|
1314
1456
|
const createTextFromClip = async (clip, fc2) => {
|
|
1315
1457
|
return new Promise(async (resolve) => {
|
|
1316
1458
|
const canvas = fc || fc2;
|
|
@@ -1391,6 +1533,7 @@ var EditorCanvas = react.forwardRef(
|
|
|
1391
1533
|
vmmlConverterRef.current.updateClip(fObj);
|
|
1392
1534
|
}
|
|
1393
1535
|
});
|
|
1536
|
+
console.log("fabricjs>>>end>>>>>>>>>>>>");
|
|
1394
1537
|
resolve(imgData);
|
|
1395
1538
|
});
|
|
1396
1539
|
});
|
|
@@ -1429,17 +1572,25 @@ var EditorCanvas = react.forwardRef(
|
|
|
1429
1572
|
};
|
|
1430
1573
|
const loadFont = async (url) => {
|
|
1431
1574
|
if (!url) return null;
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
const fontFamilyName = getFontFamilyName(url);
|
|
1435
|
-
const format = detectFontFormat(url);
|
|
1436
|
-
const fontFace = new FontFace(fontFamilyName, `url(${base64})${format ? ` format('${format}')` : ""}`);
|
|
1437
|
-
await fontFace.load();
|
|
1438
|
-
document.fonts.add(fontFace);
|
|
1439
|
-
return base64;
|
|
1440
|
-
} catch (e) {
|
|
1441
|
-
return null;
|
|
1575
|
+
if (fontCacheRef.current.has(url)) {
|
|
1576
|
+
return fontCacheRef.current.get(url);
|
|
1442
1577
|
}
|
|
1578
|
+
const loadPromise = (async () => {
|
|
1579
|
+
try {
|
|
1580
|
+
const base64 = await vmmlUtils.urlToBlob({ url });
|
|
1581
|
+
const fontFamilyName = getFontFamilyName(url);
|
|
1582
|
+
const format = detectFontFormat(url);
|
|
1583
|
+
const fontFace = new FontFace(fontFamilyName, `url(${base64})${format ? ` format('${format}')` : ""}`);
|
|
1584
|
+
await fontFace.load();
|
|
1585
|
+
document.fonts.add(fontFace);
|
|
1586
|
+
return base64;
|
|
1587
|
+
} catch (e) {
|
|
1588
|
+
console.error("Font load failed:", url, e);
|
|
1589
|
+
return null;
|
|
1590
|
+
}
|
|
1591
|
+
})();
|
|
1592
|
+
fontCacheRef.current.set(url, loadPromise);
|
|
1593
|
+
return loadPromise;
|
|
1443
1594
|
};
|
|
1444
1595
|
const setTextAlign = (p, stroke, direction) => {
|
|
1445
1596
|
if (direction === "center") {
|
|
@@ -1622,8 +1773,10 @@ var EditorCanvas = react.forwardRef(
|
|
|
1622
1773
|
}
|
|
1623
1774
|
}, [fc, dragState]);
|
|
1624
1775
|
react.useEffect(() => {
|
|
1625
|
-
if (canvasSize.width && canvasSize.height
|
|
1626
|
-
vmmlConverterRef.current
|
|
1776
|
+
if (canvasSize.width && canvasSize.height) {
|
|
1777
|
+
if (vmmlConverterRef.current) ; else {
|
|
1778
|
+
vmmlConverterRef.current = new VmmlConverter_default({ vmml, canvasSize });
|
|
1779
|
+
}
|
|
1627
1780
|
}
|
|
1628
1781
|
}, [canvasSize, vmml]);
|
|
1629
1782
|
react.useEffect(() => {
|