import { computed, nextTick, reactive } from "vue"; import { Draw } from "../container/use-draw"; import { animation } from "@/core/hook/use-animation"; import saveAs from "@/utils/file-serve"; import { ElMessage } from "element-plus"; import { Mode } from "@/constant/mode"; import { ui18n } from "@/lang"; export type Action = { handler?: (draw: Draw) => void; text?: string; icon: string; disabled?: boolean; children?: Omit[]; }; export type ActionGroups = Action[][]; const rotateView = (draw: Draw) => { const dom = draw.stage!.container(); let rotated = 0; animation({ rotation: 0 }, { rotation: Math.PI / 2 }, ({ rotation }) => { draw.viewer.rotatePixel( { x: dom.offsetWidth / 2, y: dom.offsetHeight / 2 }, rotation - rotated ); rotated = rotation; }); }; export const getImage = (draw: Draw, format: string) => draw.stage!.toBlob({ pixelRatio: 2, mimeType: format, quality: 1, }) as Promise; export const getHeaderActions = (draw: Draw) => { const floorCovers = computed(() => draw.store .getTypeItems("image") .filter((item) => item.key === "kankan-floor-cover") ); const floorCoversHide = computed(() => floorCovers.value.some((image) => image.hide) ); return { undo: reactive({ handler: () => draw.history.undo(), text: ui18n.t('sys.actions.undo'), icon: "undo", disabled: computed(() => !draw.history.hasUndo.value), }), redo: reactive({ handler: () => draw.history.redo(), text: ui18n.t('sys.actions.redo'), icon: "redo", disabled: computed(() => !draw.history.hasRedo.value), }), clear: reactive({ handler: () => { draw.store.setConfig({ compass: { ...draw.store.config.compass, rotation: 0 }, }); draw.store.clear(); }, disabled: computed(() => draw.drawing), text: ui18n.t('sys.actions.clear'), icon: "clear", }), rotateView: reactive({ handler: () => rotateView(draw), text: ui18n.t('sys.actions.rotate'), icon: "rotate", }), initViewport: reactive({ handler: () => draw.initViewport(), text: ui18n.t('sys.actions.a_adapt'), icon: "a_adapt", }), toggleShow: reactive({ handler: () => { draw.history.onceTrack(() => { const val = !floorCoversHide.value floorCovers.value.forEach((image) => { draw.store.setItem("image", { value: { ...image, hide: val }, id: image.id, }); }); }); }, text: computed(() => (floorCoversHide.value ? ui18n.t('sys.actions.floor.show') : ui18n.t('sys.actions.floor.hide'))), icon: computed(() => "visible___" + (floorCoversHide.value ? "n" : "s")), disabled: computed(() => !floorCovers.value.length) }), expose: reactive({ disabled: computed(() => draw.drawing), handler: () => {}, text: ui18n.t('sys.actions.download.name'), icon: "download", children: [ { handler: async (filename = "canvas") => { draw.enterTemp(async () => { const oldShowGrid = draw.config.showGrid; draw.config.showGrid = false; const pop = draw.mode.push(Mode.readonly); await nextTick(); const blob = await getImage(draw, "image/jpeg"); if (!blob) { throw "截图失败"; } saveAs(blob, `${filename}.jpg`); pop(); draw.config.showGrid = oldShowGrid; }); }, text: "JPG", icon: "a-visible", }, { handler: (filename = "canvas") => { draw.enterTemp(async () => { const oldBack = draw.config.back && { ...draw.config.back }; const oldShowGrid = draw.config.showGrid; const pop = draw.mode.push(Mode.readonly); draw.config.showGrid = false; draw.config.back = undefined; await nextTick(); const blob = await getImage(draw, "image/png"); if (!blob) { throw "截图失败"; } await saveAs(blob, `${filename}.png`); pop(); draw.config.back = oldBack; draw.config.showGrid = oldShowGrid; ElMessage.success(ui18n.t('sys.actions.download.success')); }); }, text: "PNG", icon: "a-visible", }, { handler: async (filename = "canvas") => { draw.enterTemp(async () => { const dxf = await draw.getDXF(); saveAs(dxf, `${filename}.zip`); }); }, text: "DXF", icon: "a-visible", }, ], }), }; };