actions.ts 4.8 KB

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