actions.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import { computed, nextTick, reactive } from "vue";
  2. import { Draw } from "../container/use-draw";
  3. import { animation } from "@/core/hook/use-animation";
  4. import saveAs from "@/utils/file-serve";
  5. import { ElMessage } from "element-plus";
  6. import { Mode } from "@/constant/mode";
  7. import { availableLocales, lang, langNameEum, ui18n } from "@/lang";
  8. import { loading } from "@/example/loadding";
  9. export type Action = {
  10. handler?: (draw: Draw) => void;
  11. text?: string;
  12. icon?: string;
  13. disabled?: boolean;
  14. children?: Omit<Action, "children">[];
  15. };
  16. export type ActionGroups = Action[][];
  17. const rotateView = (draw: Draw) => {
  18. const dom = draw.stage!.container();
  19. let rotated = 0;
  20. animation({ rotation: 0 }, { rotation: Math.PI / 2 }, ({ rotation }) => {
  21. draw.viewer.rotatePixel(
  22. { x: dom.offsetWidth / 2, y: dom.offsetHeight / 2 },
  23. rotation - rotated,
  24. );
  25. rotated = rotation;
  26. });
  27. };
  28. export const getImage = (draw: Draw, format: string) =>
  29. draw.stage!.toBlob({
  30. pixelRatio: 2,
  31. mimeType: format,
  32. quality: 1,
  33. }) as Promise<Blob | null>;
  34. export const getHeaderActions = (draw: Draw) => {
  35. const floorCovers = computed(() =>
  36. draw.store
  37. .getTypeItems("image")
  38. .filter((item) => item.key === "kankan-floor-cover"),
  39. );
  40. const floorCoversHide = computed(() =>
  41. floorCovers.value.some((image) => image.hide),
  42. );
  43. return {
  44. undo: reactive({
  45. handler: () => draw.history.undo(),
  46. text: ui18n.t("sys.actions.undo"),
  47. icon: "undo",
  48. disabled: computed(() => !draw.history.hasUndo.value),
  49. }),
  50. redo: reactive({
  51. handler: () => draw.history.redo(),
  52. text: ui18n.t("sys.actions.redo"),
  53. icon: "redo",
  54. disabled: computed(() => !draw.history.hasRedo.value),
  55. }),
  56. clear: reactive({
  57. handler: () => {
  58. draw.store.setConfig({
  59. compass: { ...draw.store.config.compass, rotation: 0 },
  60. });
  61. draw.store.clear();
  62. },
  63. disabled: computed(() => draw.drawing),
  64. text: ui18n.t("sys.actions.clear"),
  65. icon: "clear",
  66. }),
  67. rotateView: reactive({
  68. handler: () => rotateView(draw),
  69. text: ui18n.t("sys.actions.rotate"),
  70. icon: "rotate",
  71. }),
  72. initViewport: reactive({
  73. handler: () => draw.initViewport(),
  74. text: ui18n.t("sys.actions.a_adapt"),
  75. icon: "a_adapt",
  76. }),
  77. toggleShow: reactive({
  78. handler: () => {
  79. draw.history.onceTrack(() => {
  80. const val = !floorCoversHide.value;
  81. floorCovers.value.forEach((image) => {
  82. draw.store.setItem("image", {
  83. value: { ...image, hide: val },
  84. id: image.id,
  85. });
  86. });
  87. });
  88. },
  89. text: computed(() =>
  90. floorCoversHide.value
  91. ? ui18n.t("sys.actions.floor.show")
  92. : ui18n.t("sys.actions.floor.hide"),
  93. ),
  94. icon: computed(() => "visible___" + (floorCoversHide.value ? "n" : "s")),
  95. disabled: computed(() => !floorCovers.value.length),
  96. }),
  97. expose: reactive({
  98. disabled: computed(() => draw.drawing),
  99. handler: () => {},
  100. text: ui18n.t("sys.actions.download.name"),
  101. icon: "download",
  102. children: [
  103. {
  104. handler: async (filename = "canvas") => {
  105. loading(async () => {
  106. const oldShowGrid = draw.config.showGrid;
  107. draw.config.showGrid = false;
  108. const pop = draw.mode.push(Mode.readonly);
  109. await nextTick();
  110. const blob = await getImage(draw, "image/jpeg");
  111. if (!blob) {
  112. throw "截图失败";
  113. }
  114. saveAs(blob, `${filename}.jpg`);
  115. pop();
  116. draw.config.showGrid = oldShowGrid;
  117. });
  118. },
  119. text: "JPG",
  120. icon: "a-visible",
  121. },
  122. {
  123. handler: (filename = "canvas") => {
  124. loading(async () => {
  125. const oldBack = draw.config.back && { ...draw.config.back };
  126. const oldShowGrid = draw.config.showGrid;
  127. const pop = draw.mode.push(Mode.readonly);
  128. draw.config.showGrid = false;
  129. draw.config.back = undefined;
  130. await nextTick();
  131. const blob = await getImage(draw, "image/png");
  132. if (!blob) {
  133. throw "截图失败";
  134. }
  135. await saveAs(blob, `${filename}.png`);
  136. pop();
  137. draw.config.back = oldBack;
  138. draw.config.showGrid = oldShowGrid;
  139. ElMessage.success(ui18n.t("sys.actions.download.success"));
  140. });
  141. },
  142. text: "PNG",
  143. icon: "a-visible",
  144. },
  145. {
  146. handler: async (filename = "canvas") => {
  147. loading(async () => {
  148. const dxf = await draw.getDXF();
  149. saveAs(dxf, `${filename}.zip`);
  150. });
  151. },
  152. text: "DXF",
  153. icon: "a-visible",
  154. },
  155. ],
  156. }),
  157. lang: {
  158. handler: () => {},
  159. text: ui18n.t("sys.lang"),
  160. icon: "nav-geography",
  161. children: Object.keys(availableLocales).map((key) => ({
  162. text: availableLocales[key as langNameEum],
  163. handler: () => {
  164. ui18n.change(key as langNameEum);
  165. },
  166. })),
  167. },
  168. };
  169. };