@versa_ai/vmml-editor 1.0.11 → 1.0.13
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 +9 -9
- package/dist/index.js +91 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +91 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/assets/css/index.scss +68 -4
- package/src/components/EditorCanvas.tsx +37 -14
- package/src/index.tsx +6 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@versa_ai/vmml-editor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"module": "dist/index.mjs",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"types": "dist/index.d.mts",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"remotion": "4.0.166",
|
|
17
17
|
"uuid": "^10.0.0",
|
|
18
18
|
"zod": "^3.23.8",
|
|
19
|
-
"@versa_ai/vmml-
|
|
20
|
-
"@versa_ai/vmml-
|
|
19
|
+
"@versa_ai/vmml-utils": "1.0.15",
|
|
20
|
+
"@versa_ai/vmml-player": "1.1.15"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@biomejs/biome": "^1.7.1",
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
.editor{
|
|
2
2
|
background: #000;
|
|
3
3
|
width: 100%;
|
|
4
|
-
min-height: 100vh;
|
|
5
4
|
overflow: hidden;
|
|
6
5
|
display: flex;
|
|
7
6
|
flex-direction: column;
|
|
@@ -59,12 +58,16 @@
|
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
.editor-vessel {
|
|
62
|
-
|
|
61
|
+
width: 100%;
|
|
62
|
+
// padding-top: 3.2vw;
|
|
63
|
+
height: 100%;
|
|
63
64
|
}
|
|
64
65
|
//player与画布
|
|
65
66
|
.main{
|
|
66
|
-
width: 81.467vw;
|
|
67
|
-
|
|
67
|
+
// width: 81.467vw;
|
|
68
|
+
width: 100%;
|
|
69
|
+
height: 100%;
|
|
70
|
+
// height: 144.8vw;
|
|
68
71
|
margin: auto;
|
|
69
72
|
position: relative;
|
|
70
73
|
display: flex;
|
|
@@ -250,3 +253,64 @@
|
|
|
250
253
|
}
|
|
251
254
|
|
|
252
255
|
}
|
|
256
|
+
|
|
257
|
+
@media screen and (min-width: 750px) {
|
|
258
|
+
.editor {
|
|
259
|
+
.controls-box {
|
|
260
|
+
height: 20% !important;
|
|
261
|
+
border-radius: 3.2vw;
|
|
262
|
+
}
|
|
263
|
+
.player-controls {
|
|
264
|
+
display: flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
width: 100%;
|
|
267
|
+
height: 100%;
|
|
268
|
+
padding: 0 1%;
|
|
269
|
+
.mr-16 {
|
|
270
|
+
margin-right: 2.13vw;
|
|
271
|
+
}
|
|
272
|
+
.player-controls-toggle {
|
|
273
|
+
>img {
|
|
274
|
+
display: block;
|
|
275
|
+
width: 40px !important;
|
|
276
|
+
height: 40px !important;
|
|
277
|
+
cursor: pointer;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
.player-controls-seekbar {
|
|
281
|
+
flex: 1;
|
|
282
|
+
.seekbar-container {
|
|
283
|
+
height: 2px !important;
|
|
284
|
+
.seekbar-background {
|
|
285
|
+
height: 10px !important;
|
|
286
|
+
width: 100%;
|
|
287
|
+
border-radius: 1vw;
|
|
288
|
+
.seekbar-fill {
|
|
289
|
+
width: 100%;
|
|
290
|
+
height: 80%;
|
|
291
|
+
border-radius: 1vw;
|
|
292
|
+
}
|
|
293
|
+
.seekbar-line {
|
|
294
|
+
height: 100%;
|
|
295
|
+
border-radius: 1vw;
|
|
296
|
+
}
|
|
297
|
+
.seekbar-sign {
|
|
298
|
+
width: 10px;
|
|
299
|
+
top: 50%;
|
|
300
|
+
margin-top: -6px;
|
|
301
|
+
}
|
|
302
|
+
.seekbar-cirle {
|
|
303
|
+
top: -10px !important;
|
|
304
|
+
width: 40px !important;
|
|
305
|
+
height: 40px !important;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
.player-controls-time {
|
|
311
|
+
width: 6vw !important;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
@@ -347,21 +347,43 @@ const EditorCanvas = forwardRef(
|
|
|
347
347
|
waitFcTasks.current.push(createTextFromClip.bind(this, clip));
|
|
348
348
|
}
|
|
349
349
|
}
|
|
350
|
+
|
|
351
|
+
// 生成简短的字体名称
|
|
352
|
+
const getFontFamilyName = (url: string) => {
|
|
353
|
+
// 从URL中提取文件名作为字体名称
|
|
354
|
+
const filename = url.split('/').pop() || '';
|
|
355
|
+
const name = filename.replace(/\.(ttf|otf|woff2?|eot)$/i, '');
|
|
356
|
+
return `CustomFont_${name.substring(0, 20)}`; // 限制长度
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
// 检测字体格式
|
|
360
|
+
const detectFontFormat = (url: string) => {
|
|
361
|
+
const lower = url.toLowerCase();
|
|
362
|
+
if (lower.includes('.woff2')) return 'woff2';
|
|
363
|
+
if (lower.includes('.woff')) return 'woff';
|
|
364
|
+
if (lower.includes('.otf')) return 'opentype';
|
|
365
|
+
if (lower.includes('.ttf')) return 'truetype';
|
|
366
|
+
return null;
|
|
367
|
+
};
|
|
350
368
|
|
|
351
369
|
const embedFontInSVG = async (svgString: string, url: string) => {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
370
|
+
if (url) {
|
|
371
|
+
const res = await urlToBlob({ url });
|
|
372
|
+
const format = detectFontFormat(url);
|
|
373
|
+
const fontFamilyName = getFontFamilyName(url);
|
|
374
|
+
const srcValue = format ? `url('${res}') format('${format}')` : `url('${res}')`;
|
|
375
|
+
const fontFace = `
|
|
376
|
+
@font-face {
|
|
377
|
+
font-family: '${fontFamilyName}';
|
|
378
|
+
src: ${srcValue};
|
|
379
|
+
}
|
|
380
|
+
`;
|
|
381
|
+
const styleElement = `<style type="text/css"><![CDATA[${fontFace}]]></style>`;
|
|
382
|
+
const result = svgString.replace('</svg>', `${styleElement}</svg>`);
|
|
383
|
+
return result;
|
|
384
|
+
}
|
|
385
|
+
return svgString
|
|
386
|
+
}
|
|
365
387
|
|
|
366
388
|
//文字转图片
|
|
367
389
|
const createTextImg = async ({ textContent, bgColor, textColor, fontAssetUrl = null, textBasicInfo }: any) => {
|
|
@@ -373,13 +395,14 @@ const EditorCanvas = forwardRef(
|
|
|
373
395
|
container.style.display = 'inline-block'
|
|
374
396
|
container.style.textAlign = textBasicInfo.textAlign || 'left';
|
|
375
397
|
const lines = textContent.split('\n');
|
|
398
|
+
const fontFamily = fontAssetUrl ? getFontFamilyName(fontAssetUrl) : 'sansMedium';
|
|
376
399
|
lines.forEach((line: string) => {
|
|
377
400
|
const p = document.createElement('p');
|
|
378
401
|
p.style.color = textColor;
|
|
379
402
|
p.style.fontSize = '22px'
|
|
380
403
|
p.style.lineHeight = '22px'
|
|
381
404
|
const font = fontAssetUrl ? `font-${fontAssetUrl}` : 'sansMedium';
|
|
382
|
-
p.style.fontFamily =
|
|
405
|
+
p.style.fontFamily = fontFamily;
|
|
383
406
|
p.style.whiteSpace = "nowrap"
|
|
384
407
|
// p.style.backgroundColor = bgColor;
|
|
385
408
|
p.style.padding = '0';
|
package/src/index.tsx
CHANGED
|
@@ -26,6 +26,7 @@ const EditorFn = <Schema extends AnyZodObject, Props>(
|
|
|
26
26
|
editableArray = [],
|
|
27
27
|
templateId,
|
|
28
28
|
strategyId,
|
|
29
|
+
height = '100vh',
|
|
29
30
|
pauseWhenBuffering = false,
|
|
30
31
|
}: any,
|
|
31
32
|
ref: any,
|
|
@@ -444,7 +445,7 @@ const EditorFn = <Schema extends AnyZodObject, Props>(
|
|
|
444
445
|
|
|
445
446
|
return (
|
|
446
447
|
<>
|
|
447
|
-
<div className="editor">
|
|
448
|
+
<div className="editor" style={{ height }}>
|
|
448
449
|
<div className="editor-vessel" onClick={() => {
|
|
449
450
|
setMenuState("")
|
|
450
451
|
}}>
|
|
@@ -496,7 +497,8 @@ const EditorFn = <Schema extends AnyZodObject, Props>(
|
|
|
496
497
|
</section>
|
|
497
498
|
</div>
|
|
498
499
|
<div className="padding-box"></div>
|
|
499
|
-
|
|
500
|
+
{
|
|
501
|
+
(maxText > 0 || maxVideo > 0) && <section style={menuStyles} className={`footer ${menuState === 'text' ? 'text-style' : ''}`}>
|
|
500
502
|
{
|
|
501
503
|
maxText > 0 && (
|
|
502
504
|
<div
|
|
@@ -524,6 +526,8 @@ const EditorFn = <Schema extends AnyZodObject, Props>(
|
|
|
524
526
|
)
|
|
525
527
|
}
|
|
526
528
|
</section>
|
|
529
|
+
}
|
|
530
|
+
|
|
527
531
|
{
|
|
528
532
|
maxVideo > 0 && (
|
|
529
533
|
<VideoMenu menuState={menuState} createImage={createImage} videoMenus={videoMenus} />
|