header.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <template>
  2. <div class="header">
  3. <div class="nav">
  4. <el-button type="primary" plain>返回</el-button>
  5. </div>
  6. <div class="draw-operate">
  7. <div>
  8. <span
  9. class="operate"
  10. @click="draw.history.undo()"
  11. :class="{ disabled: !draw.history.hasUndo.value }"
  12. >
  13. 撤销<el-icon><Plus /></el-icon>
  14. </span>
  15. <span
  16. class="operate"
  17. @click="draw.history.redo()"
  18. :class="{ disabled: !draw.history.hasRedo.value }"
  19. >
  20. 重做<el-icon><Plus /></el-icon>
  21. </span>
  22. </div>
  23. <div>
  24. <span class="operate" @click="draw.history.clear()">
  25. 清除<el-icon><Plus /></el-icon>
  26. </span>
  27. <span class="operate" @click="rotateView">
  28. 旋转<el-icon><Plus /></el-icon>
  29. </span>
  30. <span class="operate" @click="initView">
  31. 恢复视图<el-icon><Plus /></el-icon>
  32. </span>
  33. <span class="operate" @click="emit('full')">
  34. 全屏<el-icon><Plus /></el-icon>
  35. </span>
  36. </div>
  37. <div>
  38. <span class="operate">
  39. ai导入<el-icon><Plus /></el-icon>
  40. </span>
  41. <span class="operate" @click="bgFileInput?.click()">
  42. 背景图<el-icon><Plus /></el-icon>
  43. <input
  44. class="file-input"
  45. ref="bgFileInput"
  46. type="file"
  47. @change="(ev: any) => setBGImage(ev.target.files[0])"
  48. />
  49. </span>
  50. <span class="operate">
  51. VR<el-icon><Plus /></el-icon>
  52. </span>
  53. </div>
  54. <div v-if="dev">
  55. <span class="operate" @click="draw.toggleHit()">
  56. 碰撞检测<el-icon><Plus /></el-icon>
  57. </span>
  58. </div>
  59. </div>
  60. <div class="saves">
  61. <el-button type="primary" @click="emit('expose')" plain>导出</el-button>
  62. <el-button type="primary" @click="emit('save')" plain>保存</el-button>
  63. <el-button>图纸</el-button>
  64. </div>
  65. </div>
  66. </template>
  67. <script lang="ts" setup>
  68. import { ElButton, ElIcon } from "element-plus";
  69. import { useDraw } from "../use-draw.ts";
  70. import { ref } from "vue";
  71. import { Plus } from "@element-plus/icons-vue";
  72. import { Transform } from "konva/lib/Util";
  73. import { animation } from "@/core/hook/use-animation.ts";
  74. const draw = useDraw();
  75. const bgFileInput = ref<HTMLInputElement | null>(null);
  76. const dev = import.meta.env.DEV;
  77. const emit = defineEmits<{ (e: "full"): void; (e: "save"): void; (e: "expose"): void }>();
  78. const setBGImage = (file: File) => {
  79. draw.addShape(
  80. "image",
  81. {
  82. width: window.innerWidth,
  83. height: window.innerHeight,
  84. listening: false,
  85. url: URL.createObjectURL(file),
  86. zIndex: -1,
  87. },
  88. { x: window.innerWidth / 2, y: window.innerHeight / 2 },
  89. true
  90. );
  91. };
  92. const rotateView = () => {
  93. const dom = draw.stage.container();
  94. let rotated = 0;
  95. animation({ rotation: 0 }, { rotation: Math.PI / 2 }, ({ rotation }) => {
  96. draw.viewer.rotatePixel(
  97. { x: dom.offsetWidth / 2, y: dom.offsetHeight / 2 },
  98. rotation - rotated
  99. );
  100. rotated = rotation;
  101. });
  102. };
  103. const initView = () => {
  104. animation(draw.viewer.viewMat.m, new Transform().m, (dec) => {
  105. draw.viewer.setViewMat(dec);
  106. });
  107. };
  108. </script>
  109. <style lang="scss" scoped>
  110. @use 'element-plus/theme-chalk/src/common/var';
  111. .header {
  112. background-color: var.$color-primary;
  113. display: flex;
  114. align-items: center;
  115. padding: 10px;
  116. justify-content: space-between;
  117. }
  118. .draw-operate {
  119. text-align: center;
  120. color: #fff;
  121. display: flex;
  122. align-items: center;
  123. > div:not(:last-child) {
  124. padding-right: 10px;
  125. margin-right: 10px;
  126. border-right: 1px solid #fff;
  127. }
  128. i {
  129. width: auto;
  130. }
  131. .operate {
  132. margin: 0 5px;
  133. display: inline-flex;
  134. align-items: center;
  135. font-size: 14px;
  136. flex-direction: row-reverse;
  137. justify-content: center;
  138. &.disabled {
  139. pointer-events: none;
  140. opacity: 0.7;
  141. }
  142. }
  143. }
  144. .file-input {
  145. position: absolute;
  146. visibility: hidden;
  147. }
  148. </style>