@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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @versa_ai/vmml-editor@1.0.38 build D:\code\work\vmml-player\packages\editor
2
+ > @versa_ai/vmml-editor@1.0.40 build D:\code\work\vmml-player\packages\editor
3
3
  > tsup
4
4
 
5
5
  CLI Building entry: src/index.tsx
@@ -124,12 +124,12 @@ More info and automated migrator: https://sass-lang.com/d/slash-div [35
124
124
 
125
125
 
126
126
  DTS Build start
127
- ESM dist\index.mjs 115.26 KB
128
- ESM dist\index.mjs.map 222.82 KB
129
- ESM ⚡️ Build success in 885ms
130
- CJS dist\index.js 116.86 KB
131
- CJS dist\index.js.map 223.11 KB
132
- CJS ⚡️ Build success in 886ms
133
- DTS ⚡️ Build success in 1577ms
127
+ ESM dist\index.mjs 120.82 KB
128
+ ESM dist\index.mjs.map 234.06 KB
129
+ ESM ⚡️ Build success in 753ms
130
+ CJS dist\index.js 122.51 KB
131
+ CJS dist\index.js.map 234.35 KB
132
+ CJS ⚡️ Build success in 754ms
133
+ DTS ⚡️ Build success in 2765ms
134
134
  DTS dist\index.d.ts 158.00 B
135
135
  DTS dist\index.d.mts 158.00 B
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
- existClip = originClip;
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
- originClip.duration = 0;
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
- console.log("deleteClip \u6700\u7EC8Vmml", this.vmml);
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 createTextFromClip(clip);
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
- try {
1433
- const base64 = await vmmlUtils.urlToBlob({ url });
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 && !vmmlConverterRef.current) {
1626
- vmmlConverterRef.current = new VmmlConverter_default({ vmml, canvasSize });
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(() => {