@8btc/xcanvas 0.0.14-beta.11 → 0.0.14-beta.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/dist/index.d.ts +4 -2
- package/dist/index.js +96 -3
- package/dist/index.umd.cjs +96 -3
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -42,13 +42,13 @@ export declare interface XCanvasAPI {
|
|
|
42
42
|
*/
|
|
43
43
|
exportSelection: (tryToSplit?: boolean) => Promise<string | string[]>;
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
45
|
+
* 在当前旁边插入embeddableElement元素
|
|
46
46
|
*
|
|
47
47
|
* @param data 调用 renderEmbeddable 时, 可以从 element.data 访问到这里传入的数据
|
|
48
48
|
* @param positonCalculator 入参为当前选区左上角x,y 和宽高,返回值为插入元素的左上角x,y,w,h
|
|
49
49
|
* @returns 如果成功插入返回元素id,否则返回undefined
|
|
50
50
|
*/
|
|
51
|
-
|
|
51
|
+
insertCustomElementBesideSelection: (data: {
|
|
52
52
|
component: string;
|
|
53
53
|
link?: string;
|
|
54
54
|
[key: string]: any;
|
|
@@ -75,6 +75,8 @@ export declare interface XCanvasAPI {
|
|
|
75
75
|
* 删除选区里的全部元素
|
|
76
76
|
*/
|
|
77
77
|
deleteSelection: () => void;
|
|
78
|
+
/** 插入多个视频 */
|
|
79
|
+
insertVideos: (urls: string[]) => Promise<void>;
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
export declare interface XcanvasProps extends ExcalidrawProps {
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
|
|
3
3
|
import { Excalidraw, convertToExcalidrawElements, exportToCanvas } from "@8btc/excalidraw";
|
|
4
4
|
import { useEffect } from "react";
|
|
5
|
-
const version = "0.0.14-beta.
|
|
5
|
+
const version = "0.0.14-beta.13";
|
|
6
6
|
const packageJson = {
|
|
7
7
|
version
|
|
8
8
|
};
|
|
@@ -100,6 +100,26 @@ function findPlaceForNewElements(appState, elements, newElements) {
|
|
|
100
100
|
});
|
|
101
101
|
return ret;
|
|
102
102
|
}
|
|
103
|
+
function getVideoDimensions(videoUrl) {
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
const video = document.createElement("video");
|
|
106
|
+
video.src = videoUrl;
|
|
107
|
+
video.crossOrigin = "anonymous";
|
|
108
|
+
video.onloadedmetadata = function() {
|
|
109
|
+
const width = video.videoWidth;
|
|
110
|
+
const height = video.videoHeight;
|
|
111
|
+
video.src = "";
|
|
112
|
+
video.remove();
|
|
113
|
+
resolve({ width, height });
|
|
114
|
+
};
|
|
115
|
+
video.onerror = function(err) {
|
|
116
|
+
video.src = "";
|
|
117
|
+
video.remove();
|
|
118
|
+
reject(new Error(`视频加载失败:${err}`));
|
|
119
|
+
};
|
|
120
|
+
video.load();
|
|
121
|
+
});
|
|
122
|
+
}
|
|
103
123
|
function ApiFactory() {
|
|
104
124
|
const excalidrawAPI = useAtomValue(excalidrawApiAtom);
|
|
105
125
|
const setApi = useSetAtom(apiAtom);
|
|
@@ -144,7 +164,11 @@ function ApiFactory() {
|
|
|
144
164
|
height: it.height,
|
|
145
165
|
x: places[index].x,
|
|
146
166
|
y: places[index].y,
|
|
147
|
-
fileId: it.url
|
|
167
|
+
fileId: it.url,
|
|
168
|
+
customData: {
|
|
169
|
+
naturalWidth: it.width,
|
|
170
|
+
naturalHeight: it.height
|
|
171
|
+
}
|
|
148
172
|
};
|
|
149
173
|
})
|
|
150
174
|
);
|
|
@@ -364,7 +388,7 @@ function ApiFactory() {
|
|
|
364
388
|
const base64 = canvas.toDataURL("image/png", 1);
|
|
365
389
|
return base64;
|
|
366
390
|
},
|
|
367
|
-
|
|
391
|
+
insertCustomElementBesideSelection: (data, positonCalculator) => {
|
|
368
392
|
if (!excalidrawAPI) return;
|
|
369
393
|
const appState = excalidrawAPI.getAppState();
|
|
370
394
|
const selectedElements = getSelectedElements(
|
|
@@ -476,6 +500,75 @@ function ApiFactory() {
|
|
|
476
500
|
selectedElementIds: {}
|
|
477
501
|
}
|
|
478
502
|
});
|
|
503
|
+
},
|
|
504
|
+
insertVideos: async (urls) => {
|
|
505
|
+
if (urls.length === 0) return;
|
|
506
|
+
const rets = await Promise.all(
|
|
507
|
+
urls.map(async (it) => {
|
|
508
|
+
const temp = await getVideoDimensions(it);
|
|
509
|
+
return {
|
|
510
|
+
...temp,
|
|
511
|
+
url: it
|
|
512
|
+
};
|
|
513
|
+
})
|
|
514
|
+
);
|
|
515
|
+
const places = findPlaceForNewElements(
|
|
516
|
+
excalidrawAPI.getAppState(),
|
|
517
|
+
excalidrawAPI.getSceneElements(),
|
|
518
|
+
rets
|
|
519
|
+
);
|
|
520
|
+
const els = convertToExcalidrawElements(
|
|
521
|
+
rets.map((it, index) => {
|
|
522
|
+
return {
|
|
523
|
+
type: "embeddable",
|
|
524
|
+
width: it.width,
|
|
525
|
+
height: it.height,
|
|
526
|
+
x: places[index].x,
|
|
527
|
+
y: places[index].y,
|
|
528
|
+
// 添加必需的基本样式属性
|
|
529
|
+
strokeColor: "#ffffff00",
|
|
530
|
+
backgroundColor: "transparent",
|
|
531
|
+
fillStyle: "solid",
|
|
532
|
+
strokeWidth: 2,
|
|
533
|
+
strokeStyle: "solid",
|
|
534
|
+
roundness: null,
|
|
535
|
+
roughness: 0,
|
|
536
|
+
opacity: 100,
|
|
537
|
+
id: `video-${Date.now()}`,
|
|
538
|
+
link: it.url ?? "https://www.google.com",
|
|
539
|
+
// 添加必需的变换属性
|
|
540
|
+
angle: 0,
|
|
541
|
+
seed: Math.random(),
|
|
542
|
+
version: 1,
|
|
543
|
+
versionNonce: Math.random(),
|
|
544
|
+
// 添加必需的状态属性
|
|
545
|
+
locked: false,
|
|
546
|
+
isDeleted: false,
|
|
547
|
+
groupIds: [],
|
|
548
|
+
// 添加绑定框属性
|
|
549
|
+
boundElements: [],
|
|
550
|
+
updated: Date.now(),
|
|
551
|
+
// 添加必需的索引和帧ID属性
|
|
552
|
+
frameId: null,
|
|
553
|
+
index: null,
|
|
554
|
+
// 添加缺失的index属性
|
|
555
|
+
customData: {
|
|
556
|
+
custom: true,
|
|
557
|
+
component: "video",
|
|
558
|
+
naturalWidth: it.width,
|
|
559
|
+
naturalHeight: it.height,
|
|
560
|
+
url: it.url
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
})
|
|
564
|
+
);
|
|
565
|
+
const currentElements = excalidrawAPI.getSceneElements();
|
|
566
|
+
excalidrawAPI.updateScene({
|
|
567
|
+
elements: [...currentElements, ...els]
|
|
568
|
+
});
|
|
569
|
+
excalidrawAPI.scrollToContent(els, {
|
|
570
|
+
animate: currentElements.length === 0 ? false : true
|
|
571
|
+
});
|
|
479
572
|
}
|
|
480
573
|
});
|
|
481
574
|
}, [excalidrawAPI, setApi]);
|
package/dist/index.umd.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("jotai"), require("@8btc/excalidraw"), require("react")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "jotai", "@8btc/excalidraw", "react"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.XCanvas = {}, global.jsxRuntime, global.Jotai, global.Excalidraw, global.React));
|
|
3
3
|
})(this, (function(exports2, jsxRuntime, jotai, excalidraw, react) {
|
|
4
4
|
"use strict";
|
|
5
|
-
const version = "0.0.14-beta.
|
|
5
|
+
const version = "0.0.14-beta.13";
|
|
6
6
|
const packageJson = {
|
|
7
7
|
version
|
|
8
8
|
};
|
|
@@ -100,6 +100,26 @@
|
|
|
100
100
|
});
|
|
101
101
|
return ret;
|
|
102
102
|
}
|
|
103
|
+
function getVideoDimensions(videoUrl) {
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
const video = document.createElement("video");
|
|
106
|
+
video.src = videoUrl;
|
|
107
|
+
video.crossOrigin = "anonymous";
|
|
108
|
+
video.onloadedmetadata = function() {
|
|
109
|
+
const width = video.videoWidth;
|
|
110
|
+
const height = video.videoHeight;
|
|
111
|
+
video.src = "";
|
|
112
|
+
video.remove();
|
|
113
|
+
resolve({ width, height });
|
|
114
|
+
};
|
|
115
|
+
video.onerror = function(err) {
|
|
116
|
+
video.src = "";
|
|
117
|
+
video.remove();
|
|
118
|
+
reject(new Error(`视频加载失败:${err}`));
|
|
119
|
+
};
|
|
120
|
+
video.load();
|
|
121
|
+
});
|
|
122
|
+
}
|
|
103
123
|
function ApiFactory() {
|
|
104
124
|
const excalidrawAPI = jotai.useAtomValue(excalidrawApiAtom);
|
|
105
125
|
const setApi = jotai.useSetAtom(apiAtom);
|
|
@@ -144,7 +164,11 @@
|
|
|
144
164
|
height: it.height,
|
|
145
165
|
x: places[index].x,
|
|
146
166
|
y: places[index].y,
|
|
147
|
-
fileId: it.url
|
|
167
|
+
fileId: it.url,
|
|
168
|
+
customData: {
|
|
169
|
+
naturalWidth: it.width,
|
|
170
|
+
naturalHeight: it.height
|
|
171
|
+
}
|
|
148
172
|
};
|
|
149
173
|
})
|
|
150
174
|
);
|
|
@@ -364,7 +388,7 @@
|
|
|
364
388
|
const base64 = canvas.toDataURL("image/png", 1);
|
|
365
389
|
return base64;
|
|
366
390
|
},
|
|
367
|
-
|
|
391
|
+
insertCustomElementBesideSelection: (data, positonCalculator) => {
|
|
368
392
|
if (!excalidrawAPI) return;
|
|
369
393
|
const appState = excalidrawAPI.getAppState();
|
|
370
394
|
const selectedElements = getSelectedElements(
|
|
@@ -476,6 +500,75 @@
|
|
|
476
500
|
selectedElementIds: {}
|
|
477
501
|
}
|
|
478
502
|
});
|
|
503
|
+
},
|
|
504
|
+
insertVideos: async (urls) => {
|
|
505
|
+
if (urls.length === 0) return;
|
|
506
|
+
const rets = await Promise.all(
|
|
507
|
+
urls.map(async (it) => {
|
|
508
|
+
const temp = await getVideoDimensions(it);
|
|
509
|
+
return {
|
|
510
|
+
...temp,
|
|
511
|
+
url: it
|
|
512
|
+
};
|
|
513
|
+
})
|
|
514
|
+
);
|
|
515
|
+
const places = findPlaceForNewElements(
|
|
516
|
+
excalidrawAPI.getAppState(),
|
|
517
|
+
excalidrawAPI.getSceneElements(),
|
|
518
|
+
rets
|
|
519
|
+
);
|
|
520
|
+
const els = excalidraw.convertToExcalidrawElements(
|
|
521
|
+
rets.map((it, index) => {
|
|
522
|
+
return {
|
|
523
|
+
type: "embeddable",
|
|
524
|
+
width: it.width,
|
|
525
|
+
height: it.height,
|
|
526
|
+
x: places[index].x,
|
|
527
|
+
y: places[index].y,
|
|
528
|
+
// 添加必需的基本样式属性
|
|
529
|
+
strokeColor: "#ffffff00",
|
|
530
|
+
backgroundColor: "transparent",
|
|
531
|
+
fillStyle: "solid",
|
|
532
|
+
strokeWidth: 2,
|
|
533
|
+
strokeStyle: "solid",
|
|
534
|
+
roundness: null,
|
|
535
|
+
roughness: 0,
|
|
536
|
+
opacity: 100,
|
|
537
|
+
id: `video-${Date.now()}`,
|
|
538
|
+
link: it.url ?? "https://www.google.com",
|
|
539
|
+
// 添加必需的变换属性
|
|
540
|
+
angle: 0,
|
|
541
|
+
seed: Math.random(),
|
|
542
|
+
version: 1,
|
|
543
|
+
versionNonce: Math.random(),
|
|
544
|
+
// 添加必需的状态属性
|
|
545
|
+
locked: false,
|
|
546
|
+
isDeleted: false,
|
|
547
|
+
groupIds: [],
|
|
548
|
+
// 添加绑定框属性
|
|
549
|
+
boundElements: [],
|
|
550
|
+
updated: Date.now(),
|
|
551
|
+
// 添加必需的索引和帧ID属性
|
|
552
|
+
frameId: null,
|
|
553
|
+
index: null,
|
|
554
|
+
// 添加缺失的index属性
|
|
555
|
+
customData: {
|
|
556
|
+
custom: true,
|
|
557
|
+
component: "video",
|
|
558
|
+
naturalWidth: it.width,
|
|
559
|
+
naturalHeight: it.height,
|
|
560
|
+
url: it.url
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
})
|
|
564
|
+
);
|
|
565
|
+
const currentElements = excalidrawAPI.getSceneElements();
|
|
566
|
+
excalidrawAPI.updateScene({
|
|
567
|
+
elements: [...currentElements, ...els]
|
|
568
|
+
});
|
|
569
|
+
excalidrawAPI.scrollToContent(els, {
|
|
570
|
+
animate: currentElements.length === 0 ? false : true
|
|
571
|
+
});
|
|
479
572
|
}
|
|
480
573
|
});
|
|
481
574
|
}, [excalidrawAPI, setApi]);
|