Skip to content

Commit 4d84318

Browse files
committed
feat: optimize data processing
1 parent 70228aa commit 4d84318

13 files changed

Lines changed: 109 additions & 158 deletions

File tree

example/index.tsx

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ import ReactDOM from "react-dom";
33
import type { FC } from "react";
44
import { useEffect, useRef, useState } from "react";
55
import { SVG_DATA, XML_DATA } from "./constant";
6-
import { base64ToSvgString, stringToSvg, stringToXml, xmlToString } from "./utils";
76
import { clearElement } from "./utils";
8-
import { diagramLoader } from "./loader";
7+
import { loadEditor, loadViewer } from "./loader";
8+
import { stringToXml, xmlToString } from "../src/utils/xml";
9+
import { base64ToSvgString, stringToSvg } from "../src/utils/svg";
10+
import { getLanguage } from "../src/editor/i18n";
11+
import { EditorBus } from "../src/event";
912

1013
const DiagramExample: FC = () => {
1114
const [loading, setLoading] = useState(true);
@@ -15,16 +18,17 @@ const DiagramExample: FC = () => {
1518
const svgExampleContainer = useRef<HTMLDivElement>(null);
1619

1720
useEffect(() => {
18-
diagramLoader().then(() => {
21+
// Preload Diagram
22+
Promise.all([loadEditor(), loadViewer()]).then(() => {
1923
setLoading(false);
20-
}); // Preload Diagram
24+
});
2125
}, []);
2226

2327
const convertXML = (xml: string = xmlExample) => {
2428
const div = xmlExampleContainer.current;
2529
if (div) {
26-
diagramLoader().then(diagram => {
27-
const diagramViewer = new diagram.DiagramViewer(stringToXml(xml));
30+
loadViewer().then(Viewer => {
31+
const diagramViewer = new Viewer(stringToXml(xml));
2832
const svg = diagramViewer.renderSVG(null, 1, 1);
2933
diagramViewer.destroy();
3034
clearElement(div);
@@ -42,42 +46,32 @@ const DiagramExample: FC = () => {
4246
}
4347
};
4448

45-
const editXML = () => {
46-
diagramLoader().then(diagram => {
47-
const renderExit = (el: HTMLDivElement) => {
48-
ReactDOM.render(
49-
<div onClick={diagramEditor.exit} className="diagram-exit-btn">
50-
退出
51-
</div>,
52-
el
53-
);
54-
};
55-
const diagramEditor = new diagram.DiagramEditor(document.body, renderExit);
56-
diagram.getLanguage("zh").then(res => {
57-
diagramEditor.start(res, stringToXml(xmlExample), (xml: Node) => {
58-
const xmlString = xmlToString(xml);
59-
xmlString && setXMLExample(xmlString);
60-
xmlString && convertXML(xmlString);
61-
});
62-
});
49+
const editXML = async () => {
50+
const Editor = await loadEditor();
51+
const diagramEditor = new Editor(document.body, () => {
52+
diagramEditor.exit();
53+
});
54+
const lang = await getLanguage("zh");
55+
diagramEditor.start(lang, stringToXml(xmlExample), (xml: Node) => {
56+
const xmlString = xmlToString(xml);
57+
xmlString && setXMLExample(xmlString);
58+
xmlString && convertXML(xmlString);
6359
});
6460
};
6561

6662
const editSVG = () => {
67-
diagramLoader().then(diagram => {
68-
const bus = new diagram.EditorBus({
69-
data: svgExample,
70-
format: "xmlsvg",
71-
onExport: (svg: string) => {
72-
const svgStr = base64ToSvgString(svg);
73-
if (svgStr) {
74-
setSVGExample(svgStr);
75-
convertSVG(svgStr);
76-
}
77-
},
78-
});
79-
bus.startEdit();
63+
const bus = new EditorBus({
64+
data: svgExample,
65+
format: "xmlsvg",
66+
onExport: (svg: string) => {
67+
const svgStr = base64ToSvgString(svg);
68+
if (svgStr) {
69+
setSVGExample(svgStr);
70+
convertSVG(svgStr);
71+
}
72+
},
8073
});
74+
bus.startEdit();
8175
};
8276

8377
return (

example/loader.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
import type * as Diagram from "../src";
1+
import type { DiagramEditor } from "../src/core/editor";
2+
import type { DiagramViewer } from "../src/core/viewer";
23

3-
let instance: typeof Diagram | null = null;
4+
let editor: typeof DiagramEditor | null = null;
5+
let viewer: typeof DiagramViewer | null = null;
46

5-
export const diagramLoader = (): Promise<typeof Diagram> => {
6-
if (instance) return Promise.resolve(instance);
7-
return import("../src").then(res => {
8-
instance = res;
9-
return res;
7+
export const loadEditor = (): Promise<typeof DiagramEditor> => {
8+
if (editor) return Promise.resolve(editor);
9+
return import("../src/core/editor").then(res => {
10+
editor = res.DiagramEditor;
11+
return editor;
12+
});
13+
};
14+
15+
export const loadViewer = (): Promise<typeof DiagramViewer> => {
16+
if (viewer) return Promise.resolve(viewer);
17+
return import("../src/core/viewer").then(res => {
18+
viewer = res.DiagramViewer;
19+
return viewer;
1020
});
1121
};

example/utils.ts

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,9 @@
1+
import { xmlToString } from "../src/utils/xml";
2+
13
export const clearElement = (element: HTMLElement | null): void => {
24
element && element.childNodes.forEach(node => element.removeChild(node));
35
};
46

57
export const getDrawIOSvgString = (xml: XMLDocument) => {
68
return xmlToString(xml.documentElement.firstChild?.firstChild || null);
79
};
8-
9-
export const xmlToString = (xml: Node | null): string | null => {
10-
if (!xml) return null;
11-
try {
12-
const serialize = new XMLSerializer();
13-
return serialize.serializeToString(xml);
14-
} catch (error) {
15-
console.log("XmlToString Error: ", error);
16-
return null;
17-
}
18-
};
19-
20-
export const stringToXml = (str: string): XMLDocument | null => {
21-
try {
22-
const parser = new DOMParser();
23-
return parser.parseFromString(str, "text/xml") as XMLDocument;
24-
} catch (error) {
25-
console.log("StringToXml Error: ", error);
26-
return null;
27-
}
28-
};
29-
30-
export const svgToString = (svg: Node | null): string | null => {
31-
if (!svg) return null;
32-
try {
33-
const serialize = new XMLSerializer();
34-
return serialize.serializeToString(svg);
35-
} catch (error) {
36-
console.log("SvgToString Error: ", error);
37-
return null;
38-
}
39-
};
40-
41-
export const stringToSvg = (str: string): SVGElement | null => {
42-
try {
43-
const parser = new DOMParser();
44-
return parser.parseFromString(str, "image/svg+xml").firstChild as SVGElement;
45-
} catch (error) {
46-
console.log("StringToSvg Error: ", error);
47-
return null;
48-
}
49-
};
50-
51-
export const base64ToSvgString = (base64: string): string | null => {
52-
try {
53-
const svg = atob(base64.replace("data:image/svg+xml;base64,", ""));
54-
return svg;
55-
} catch (error) {
56-
console.log("base64ToSvgString Error: ", error);
57-
return null;
58-
}
59-
};

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"build:es": "tsc -p tsconfig.build.json",
1919
"build:lib": "tsc -p tsconfig.lib.json",
2020
"build:css": "gulp -f gulpfile.js",
21-
"build:npm": "rm -rf ./dist && npm run build:es && npm run build:lib && npm run build:css",
21+
"build:dist": "rm -rf ./dist && npm run build:es && npm run build:lib && npm run build:css",
2222
"lint:es": "eslint --fix --ext .js,.jsx,.ts,.tsx --ignore-path .gitignore .",
2323
"lint:style": "stylelint \"**/*.{css,scss,sass}\" --fix --ignore-path .gitignore",
2424
"lint": "npm run lint-es && npm run lint-style"

publish.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
npm version patch --no-git-tag-version
2-
npm run build:packages
2+
npm run build:dist
33
npm publish --registry=https://registry.npmjs.org/

src/core/editor.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import "../editor/styles/common.css";
22
import "../editor/styles/grapheditor.css";
33
import "../styles/diagram.css";
4-
import { stringToXml, xmlToString } from "../utils/xml";
4+
import { stringToXml } from "../utils/xml";
55
import { DEFAULT_STYLE_XML } from "../styles/default";
66
import { Editor, EditorUi, Graph } from "../editor";
77
import { mxEvent, mxResources } from "./mxgraph";
88
import type { Language } from "../editor/i18n";
9-
import { getLanguage } from "../editor/i18n";
109

1110
const themes: Record<string, Node> = {};
1211
themes[Graph.prototype.defaultThemeName] = (
@@ -18,10 +17,7 @@ export class DiagramEditor {
1817
private editorUi: EditorUi | null;
1918
private diagramContainer: HTMLElement;
2019

21-
constructor(
22-
private container: HTMLElement,
23-
private createExitButton: (container: HTMLDivElement) => void
24-
) {
20+
constructor(private container: HTMLElement, private onExit: () => void) {
2521
this.editor = null;
2622
this.editorUi = null;
2723
this.diagramContainer = document.createElement("div");
@@ -37,7 +33,7 @@ export class DiagramEditor {
3733
this.container.style.overflow = "hidden";
3834
mxResources.parse(lang);
3935
this.editor = new Editor(false, themes);
40-
this.editorUi = new EditorUi(this.editor, this.diagramContainer, null, this.createExitButton);
36+
this.editorUi = new EditorUi(this.editor, this.diagramContainer, null, this.onExit);
4137
if (init) {
4238
this.editorUi.editor.setGraphXml(init.documentElement);
4339
}
@@ -55,5 +51,3 @@ export class DiagramEditor {
5551
this.container.removeChild(this.diagramContainer);
5652
};
5753
}
58-
59-
export { stringToXml, getLanguage, xmlToString };

src/core/viewer.ts

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { stringToXml, xmlToString } from "../utils/xml";
1+
import { stringToXml } from "../utils/xml";
22
import { DEFAULT_STYLE_XML } from "../styles/default";
33
import { Graph } from "../editor";
44
import { mxCodec, mxEvent } from "./mxgraph";
5-
import { stringToSvg, svgToString } from "../utils/svg";
65

76
const themes: Record<string, Node> = {};
87
themes[Graph.prototype.defaultThemeName] = (
@@ -41,50 +40,3 @@ export class DiagramViewer {
4140
this.container = null;
4241
};
4342
}
44-
45-
export const convertSVGToBase64 = (xml: string | XMLDocument): string | null => {
46-
const xmlDoc = typeof xml === "string" ? stringToXml(xml) : xml;
47-
const viewer = new DiagramViewer(xmlDoc);
48-
const svg = viewer.renderSVG(null, 1, 1);
49-
const svgString = svgToString(svg);
50-
if (svgString) {
51-
return "data:image/svg+xml;base64," + btoa(svgString);
52-
}
53-
return null;
54-
};
55-
56-
export const downloadSVG = (
57-
xml: string | XMLDocument,
58-
name = "image.jpg"
59-
): Promise<(() => void) | null> => {
60-
return new Promise(r => {
61-
const svgBase64 = convertSVGToBase64(xml);
62-
if (svgBase64) {
63-
const image = new Image();
64-
image.crossOrigin = "anonymous";
65-
image.onload = () => {
66-
const canvas = document.createElement("canvas");
67-
const ratio = window.devicePixelRatio || 1;
68-
canvas.width = image.width * ratio;
69-
canvas.height = image.height * ratio;
70-
const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
71-
ctx.scale(ratio, ratio);
72-
ctx.fillStyle = "#fff";
73-
ctx.fillRect(0, 0, canvas.width, canvas.height);
74-
ctx.drawImage(image, 0, 0);
75-
const exportFn = () => {
76-
const link = document.createElement("a");
77-
link.download = name;
78-
link.href = canvas.toDataURL("image/jpeg");
79-
link.click();
80-
};
81-
r(exportFn);
82-
};
83-
image.src = svgBase64;
84-
} else {
85-
r(null);
86-
}
87-
});
88-
};
89-
90-
export { stringToXml, svgToString, xmlToString, stringToSvg };

src/editor/i18n/lang-en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,4 +322,5 @@ zoom=Zoom
322322
zoomIn=Zoom In
323323
zoomOut=Zoom Out
324324
flowchart=Flow Chart
325+
exit=Exit
325326
`;

src/editor/i18n/lang-zh.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,4 +323,5 @@ zoom=缩放
323323
zoomIn=放大
324324
zoomOut=缩小
325325
flowchart=流程图
326+
exit=退出
326327
`;

src/editor/js/EditorUi.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export { ChangePageSetup, EditorUi };
4141
/**
4242
* Constructs a new graph editor
4343
*/
44-
function EditorUi(editor, container, lightbox, renderExitButton) {
44+
function EditorUi(editor, container, lightbox, onExit) {
4545
mxEventSource.call(this);
4646

4747
this.destroyFunctions = [];
@@ -104,7 +104,11 @@ function EditorUi(editor, container, lightbox, renderExitButton) {
104104
this.createUi();
105105
this.refresh();
106106

107-
renderExitButton && renderExitButton(this.exitButton);
107+
const exit = document.createElement("div");
108+
exit.className = "diagram-exit-btn";
109+
exit.innerText = mxResources.get("exit");
110+
exit.onclick = onExit;
111+
this.exitButton.appendChild(exit);
108112

109113
// Disables HTML and text selection
110114
const textEditing = mxUtils.bind(this, function (evt) {

0 commit comments

Comments
 (0)