123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- <template>
- <div class="header">
- <div class="nav">
- <el-button type="primary" plain>返回</el-button>
- </div>
- <div class="draw-operate">
- <div>
- <span
- class="operate"
- @click="draw.history.undo()"
- :class="{ disabled: !draw.history.hasUndo.value }"
- >
- 撤销<el-icon><Plus /></el-icon>
- </span>
- <span
- class="operate"
- @click="draw.history.redo()"
- :class="{ disabled: !draw.history.hasRedo.value }"
- >
- 重做<el-icon><Plus /></el-icon>
- </span>
- </div>
- <div>
- <span class="operate" @click="draw.history.clear()">
- 清除<el-icon><Plus /></el-icon>
- </span>
- <span class="operate" @click="rotateView">
- 旋转<el-icon><Plus /></el-icon>
- </span>
- <span class="operate" @click="initView">
- 恢复视图<el-icon><Plus /></el-icon>
- </span>
- <span class="operate" @click="emit('full')">
- 全屏<el-icon><Plus /></el-icon>
- </span>
- </div>
- <div>
- <span class="operate">
- ai导入<el-icon><Plus /></el-icon>
- </span>
- <span class="operate" @click="bgFileInput?.click()">
- 背景图<el-icon><Plus /></el-icon>
- <input
- class="file-input"
- ref="bgFileInput"
- type="file"
- @change="(ev: any) => setBGImage(ev.target.files[0])"
- />
- </span>
- <span class="operate">
- VR<el-icon><Plus /></el-icon>
- </span>
- </div>
- <div v-if="dev">
- <span class="operate" @click="draw.toggleHit()">
- 碰撞检测<el-icon><Plus /></el-icon>
- </span>
- </div>
- </div>
- <div class="saves">
- <el-button type="primary" @click="emit('expose')" plain>导出</el-button>
- <el-button type="primary" @click="emit('save')" plain>保存</el-button>
- <el-button>图纸</el-button>
- </div>
- </div>
- </template>
- <script lang="ts" setup>
- import { ElButton, ElIcon } from "element-plus";
- import { useDraw } from "../use-draw.ts";
- import { ref } from "vue";
- import { Plus } from "@element-plus/icons-vue";
- import { Transform } from "konva/lib/Util";
- import { animation } from "@/core/hook/use-animation.ts";
- const draw = useDraw();
- const bgFileInput = ref<HTMLInputElement | null>(null);
- const dev = import.meta.env.DEV;
- const emit = defineEmits<{ (e: "full"): void; (e: "save"): void; (e: "expose"): void }>();
- const setBGImage = (file: File) => {
- draw.addShape(
- "image",
- {
- width: window.innerWidth,
- height: window.innerHeight,
- listening: false,
- url: URL.createObjectURL(file),
- zIndex: -1,
- },
- { x: window.innerWidth / 2, y: window.innerHeight / 2 },
- true
- );
- };
- const rotateView = () => {
- 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;
- });
- };
- const initView = () => {
- animation(draw.viewer.viewMat.m, new Transform().m, (dec) => {
- draw.viewer.setViewMat(dec);
- });
- };
- </script>
- <style lang="scss" scoped>
- @use 'element-plus/theme-chalk/src/common/var';
- .header {
- background-color: var.$color-primary;
- display: flex;
- align-items: center;
- padding: 10px;
- justify-content: space-between;
- }
- .draw-operate {
- text-align: center;
- color: #fff;
- display: flex;
- align-items: center;
- > div:not(:last-child) {
- padding-right: 10px;
- margin-right: 10px;
- border-right: 1px solid #fff;
- }
- i {
- width: auto;
- }
- .operate {
- margin: 0 5px;
- display: inline-flex;
- align-items: center;
- font-size: 14px;
- flex-direction: row-reverse;
- justify-content: center;
- &.disabled {
- pointer-events: none;
- opacity: 0.7;
- }
- }
- }
- .file-input {
- position: absolute;
- visibility: hidden;
- }
- </style>
|