2026-03-06 15:50:05 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="depth-canvas">
|
|
|
|
|
<div class="canvas-container" ref="canvasContainerRef">
|
|
|
|
|
<canvas ref="canvasRef"></canvas>
|
|
|
|
|
</div>
|
|
|
|
|
<layer-panel />
|
|
|
|
|
<details-panel />
|
|
|
|
|
<header-tools />
|
2026-03-09 13:44:32 +08:00
|
|
|
<zoom
|
|
|
|
|
:zoom="canvasManager.currentZoom.value / 100"
|
|
|
|
|
:step="0.1"
|
|
|
|
|
is-home
|
|
|
|
|
@home="() => canvasManager.resetZoom()"
|
|
|
|
|
/>
|
2026-03-06 15:50:05 +08:00
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { fabric } from 'fabric-with-all'
|
|
|
|
|
import { computed, ref, markRaw, onMounted, nextTick, provide, onBeforeMount } from 'vue'
|
|
|
|
|
import { NODE_TYPE, NODE_COMPONENT } from './tools/index.d'
|
|
|
|
|
// 组件
|
|
|
|
|
import layerPanel from './components/layer-panel/index.vue'
|
|
|
|
|
import detailsPanel from './components/details-panel/index.vue'
|
|
|
|
|
import headerTools from './components/header-tools.vue'
|
|
|
|
|
import zoom from '../components/zoom.vue'
|
|
|
|
|
|
|
|
|
|
// 管理器
|
|
|
|
|
import { StateManager } from './manager/StateManager'
|
|
|
|
|
import { EventManager } from './manager/EventManager'
|
2026-03-09 13:44:32 +08:00
|
|
|
import { CanvasManager } from './manager/CanvasManager'
|
|
|
|
|
import { ToolManager } from './manager/ToolManager'
|
2026-03-06 15:50:05 +08:00
|
|
|
|
|
|
|
|
const canvasContainerRef = ref(null)
|
|
|
|
|
const canvasRef = ref(null)
|
|
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
config: {
|
|
|
|
|
type: Object,
|
|
|
|
|
default: () => ({})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 状态管理器
|
|
|
|
|
const stateManager = new StateManager({})
|
|
|
|
|
provide('stateManager', stateManager)
|
|
|
|
|
|
2026-03-09 13:44:32 +08:00
|
|
|
// 画布管理器
|
|
|
|
|
const canvasManager = new CanvasManager({ stateManager })
|
|
|
|
|
stateManager.setManager({ canvasManager, canvasRef })
|
|
|
|
|
provide('canvasManager', canvasManager)
|
|
|
|
|
|
2026-03-06 15:50:05 +08:00
|
|
|
// 事件管理器
|
|
|
|
|
const eventManager = new EventManager({ stateManager })
|
|
|
|
|
stateManager.setManager({ eventManager })
|
|
|
|
|
provide('eventManager', eventManager)
|
|
|
|
|
|
|
|
|
|
// 工具管理器
|
2026-03-09 13:44:32 +08:00
|
|
|
const toolManager = new ToolManager({ stateManager, canvasManager })
|
2026-03-06 15:50:05 +08:00
|
|
|
stateManager.setManager({ toolManager })
|
|
|
|
|
provide('toolManager', toolManager)
|
2026-03-09 13:44:32 +08:00
|
|
|
|
|
|
|
|
const observer = ref(null)
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
canvasManager.initCanvas({
|
|
|
|
|
canvasRef,
|
|
|
|
|
canvasViewWidth: canvasContainerRef.value.clientWidth,
|
|
|
|
|
canvasViewHeight: canvasContainerRef.value.clientHeight,
|
|
|
|
|
canvasWidth: 750,
|
|
|
|
|
canvasHeight: 600
|
2026-03-06 15:50:05 +08:00
|
|
|
})
|
2026-03-09 13:44:32 +08:00
|
|
|
|
|
|
|
|
const trailingTimeout = ref(null)
|
|
|
|
|
observer.value = new ResizeObserver((entries) => {
|
|
|
|
|
clearTimeout(trailingTimeout.value)
|
|
|
|
|
trailingTimeout.value = setTimeout(async () => {
|
|
|
|
|
handleWindowResize()
|
|
|
|
|
}, 100)
|
2026-03-06 15:50:05 +08:00
|
|
|
})
|
2026-03-09 13:44:32 +08:00
|
|
|
observer.value.observe(canvasContainerRef.value)
|
2026-03-06 15:50:05 +08:00
|
|
|
})
|
|
|
|
|
onBeforeMount(() => {
|
|
|
|
|
// eventManager.removeEvents() // 移除事件
|
|
|
|
|
})
|
2026-03-09 13:44:32 +08:00
|
|
|
async function handleWindowResize() {
|
|
|
|
|
console.log('==========画布窗口大小变化==========')
|
|
|
|
|
canvasManager.setCanvasViewSize({
|
|
|
|
|
canvasViewWidth: canvasContainerRef.value.clientWidth,
|
|
|
|
|
canvasViewHeight: canvasContainerRef.value.clientHeight
|
|
|
|
|
})
|
|
|
|
|
canvasManager.resetZoom()
|
|
|
|
|
}
|
2026-03-06 15:50:05 +08:00
|
|
|
</script>
|
|
|
|
|
<style lang="less">
|
|
|
|
|
@import '@vue-flow/core/dist/style.css';
|
|
|
|
|
@import '@vue-flow/core/dist/theme-default.css';
|
|
|
|
|
</style>
|
|
|
|
|
<style lang="less" scoped>
|
|
|
|
|
.depth-canvas {
|
|
|
|
|
position: relative;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
user-select: none;
|
|
|
|
|
> .canvas-container {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
> canvas {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
&:deep(.canvas-container) {
|
|
|
|
|
filter: drop-shadow(0 0 5px rgba(0, 0, 0, 0.3));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|