You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
General-AI-Platform-Web-Client/src/core/ServersPlugin.ts

259 lines
6.8 KiB
TypeScript

/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-29 09:31:35
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-06 17:12:48
* @FilePath: \vue-fabric-editor\src\core\ServersPlugin.ts
* @Description:
*/
import { v4 as uuid } from "uuid";
import { selectFiles, clipboardText } from "@/utils/utils";
// import { clipboardText } from '@/utils/utils.ts';
import { fabric } from "fabric";
import Editor from "../core";
import { customJsonAttr } from "@/hooks/config";
type IEditor = Editor;
// import { v4 as uuid } from 'uuid';
function downFile(fileStr: string, fileType: string) {
const anchorEl = document.createElement("a");
anchorEl.href = fileStr;
anchorEl.download = `${uuid()}.${fileType}`;
document.body.appendChild(anchorEl); // required for firefox
anchorEl.click();
anchorEl.remove();
}
function transformText(objects) {
if (!objects) return;
objects.forEach(item => {
if (item.objects) {
transformText(item.objects);
} else {
item.type === "text" && (item.type = "textbox");
}
});
}
class ServersPlugin {
public canvas: fabric.Canvas;
public editor: IEditor;
static pluginName = "ServersPlugin";
public elementHandler: ElementHandler;
static apis = [
"insert",
"insertSvgFile",
"getJson",
"dragAddItem",
"clipboard",
"saveJson",
"saveSvg",
"saveImg",
"clear",
"preview"
];
// public hotkeys: string[] = ['left', 'right', 'down', 'up'];
constructor(canvas: fabric.Canvas, editor: IEditor) {
this.canvas = canvas;
this.editor = editor;
}
insert() {
selectFiles({ accept: ".json" }).then(files => {
const [file] = files;
const reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = () => {
this.insertSvgFile(reader.result);
};
});
}
insertSvgFile(jsonFile) {
console.log(jsonFile, "insertSvgFile");
// 加载前钩子
this.editor.hooksEntity.hookImportBefore.callAsync(jsonFile, () => {
this.canvas.loadFromJSON(jsonFile, () => {
this.canvas.renderAll();
// 加载后钩子
this.editor.hooksEntity.hookImportAfter.callAsync(jsonFile, () => {
this.canvas.renderAll();
});
});
});
}
/**
* Set partial by object
* @param {FabricObject} obj
* @param {FabricObjectOption} option
* @returns
*/
// setByPartial(obj: FabricObject, option: FabricObjectOption) {
// if (!obj) {
// return;
// }
// if (obj.type === 'svg') {
// if (option.fill) {
// obj.setFill(option.fill);
// } else if (option.stroke) {
// obj.setStroke(option.stroke);
// }
// }
// obj.set(option);
// obj.setCoords();
// this.canvas.renderAll();
// const { id, superType, type, player, width, height } = obj as any;
// if (superType === 'element') {
// if ('visible' in option) {
// if (option.visible) {
// obj.element.style.display = 'block';
// } else {
// obj.element.style.display = 'none';
// }
// }
// const el = this.elementHandler.findById(id);
// // update the element
// this.elementHandler.setScaleOrAngle(el, obj);
// this.elementHandler.setSize(el, obj);
// this.elementHandler.setPosition(el, obj);
// if (type === 'video' && player) {
// player.setPlayerSize(width, height);
// }
// }
// }
getJson() {
// update 在json对象中新增的属性需要在此备注
return this.canvas.toJSON([...customJsonAttr]);
}
/**
* @description:
* @param {Event} event
* @param {Object} item
*/
dragAddItem(event: DragEvent, item: fabric.Object) {
const { left, top } = this.canvas
.getSelectionElement()
.getBoundingClientRect();
if (event.x < left || event.y < top || item.width === undefined) return;
const point = {
x: event.x - left,
y: event.y - top
};
const pointerVpt = this.canvas.restorePointerVpt(point);
item.left = pointerVpt.x - item.width / 2;
item.top = pointerVpt.y;
this.canvas.add(item);
this.canvas.requestRenderAll();
}
clipboard() {
const jsonStr = this.getJson();
clipboardText(JSON.stringify(jsonStr, null, "\t"));
}
async saveJson() {
const dataUrl = this.getJson();
console.log(dataUrl, "saveJson_dataUrl");
// 把文本text转为textgroup让导入可以编辑
await transformText(dataUrl.objects);
const fileStr = `data:text/json;charset=utf-8,${encodeURIComponent(
JSON.stringify({ ...dataUrl }, null, "\t")
)}`;
downFile(fileStr, "json");
}
saveSvg() {
this.editor.hooksEntity.hookSaveBefore.callAsync("", () => {
const option = this._getSaveSvgOption();
const dataUrl = this.canvas.toSVG(option);
const fileStr = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(
dataUrl
)}`;
this.editor.hooksEntity.hookSaveAfter.callAsync(fileStr, () => {
downFile(fileStr, "svg");
});
});
}
saveImg() {
this.editor.hooksEntity.hookSaveBefore.callAsync("", () => {
const option = this._getSaveOption();
this.canvas.setViewportTransform([1, 0, 0, 1, 0, 0]);
const dataUrl = this.canvas.toDataURL(option);
this.editor.hooksEntity.hookSaveAfter.callAsync(dataUrl, () => {
downFile(dataUrl, "png");
});
});
}
preview() {
return new Promise((resolve, _) => {
this.editor.hooksEntity.hookSaveBefore.callAsync("", () => {
const option = this._getSaveOption();
this.canvas.setViewportTransform([1, 0, 0, 1, 0, 0]);
this.canvas.renderAll();
const dataUrl = this.canvas.toDataURL(option);
this.editor.hooksEntity.hookSaveAfter.callAsync(dataUrl, () => {
resolve(dataUrl);
});
});
});
}
_getSaveSvgOption() {
const workspace = this.canvas
.getObjects()
.find(item => item.id === "workspace");
const { left, top, width, height } = workspace;
return {
width,
height,
viewBox: {
x: left,
y: top,
width,
height
}
};
}
_getSaveOption() {
const workspace = this.canvas
.getObjects()
.find((item: fabric.Object) => item.id === "workspace");
const { left, top, width, height } = workspace as fabric.Object;
const option = {
name: "New Image",
format: "png",
quality: 1,
width,
height,
left,
top
};
return option;
}
clear() {
this.canvas.getObjects().forEach(obj => {
if (obj.id !== "workspace") {
this.canvas.remove(obj);
}
});
this.canvas.discardActiveObject();
this.canvas.renderAll();
}
destroy() {
console.log("pluginDestroy");
}
}
export default ServersPlugin;