|
|
@@ -1,5 +1,12 @@
|
|
|
<template>
|
|
|
- <div ref="viewportRef" class="main-panel overflow-hidden w-1/1 h-1/1" @wheel="onMouseWheel">
|
|
|
+ <div
|
|
|
+ ref="viewportRef"
|
|
|
+ class="main-panel overflow-hidden w-1/1 h-1/1"
|
|
|
+ :class="{
|
|
|
+ 'main-panel--pan-mode': panModeEnabled,
|
|
|
+ 'main-panel--panning': ['beginDragCanvas', 'runDragCanvas'].includes(globalStore.intention)
|
|
|
+ }"
|
|
|
+ @wheel="onMouseWheel">
|
|
|
<div
|
|
|
id="mtCanvasArea"
|
|
|
ref="canvasAreaRef"
|
|
|
@@ -69,7 +76,35 @@
|
|
|
:menu-info="contextMenuStore.menuInfo"
|
|
|
:show="globalStore.intention == 'showContextMenu'"
|
|
|
@on-context-menu-click="onContextMenuClick" />
|
|
|
- <div class="zoom-toolbar" role="toolbar" aria-label="画布缩放" @mousedown.stop @click.stop>
|
|
|
+ <div
|
|
|
+ class="zoom-toolbar"
|
|
|
+ role="toolbar"
|
|
|
+ aria-label="画布操作与缩放"
|
|
|
+ @mousedown.stop
|
|
|
+ @click.stop>
|
|
|
+ <div class="zoom-toolbar__modes" aria-label="画布操作模式">
|
|
|
+ <el-tooltip content="选择组件或框选" placement="top">
|
|
|
+ <el-button
|
|
|
+ class="zoom-toolbar__icon zoom-toolbar__mode"
|
|
|
+ :class="{ 'is-active': !panModeEnabled }"
|
|
|
+ text
|
|
|
+ aria-label="切换到选择模式"
|
|
|
+ @click="panModeEnabled = false">
|
|
|
+ <el-icon><Pointer /></el-icon>
|
|
|
+ </el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ <el-tooltip content="按住左键拖动画布" placement="top">
|
|
|
+ <el-button
|
|
|
+ class="zoom-toolbar__icon zoom-toolbar__mode"
|
|
|
+ :class="{ 'is-active': panModeEnabled }"
|
|
|
+ text
|
|
|
+ aria-label="切换到画布拖拽模式"
|
|
|
+ @click="panModeEnabled = true">
|
|
|
+ <el-icon><Rank /></el-icon>
|
|
|
+ </el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ </div>
|
|
|
+ <span class="zoom-toolbar__divider"></span>
|
|
|
<el-tooltip content="缩小 10%" placement="top">
|
|
|
<el-button
|
|
|
class="zoom-toolbar__icon"
|
|
|
@@ -143,7 +178,7 @@ import ContextMenu from '@/components/mt-edit/components/context-menu/index.vue'
|
|
|
import { contextMenuStore } from '@/components/mt-edit/store/context-menu'
|
|
|
import DrawLineRender from '@/components/mt-edit/components/draw-line-render/index.vue'
|
|
|
import { configStore } from '@/components/mt-edit/store/config'
|
|
|
-import { FullScreen, Minus, Plus } from '@element-plus/icons-vue'
|
|
|
+import { FullScreen, Minus, Plus, Pointer, Rank } from '@element-plus/icons-vue'
|
|
|
import {
|
|
|
calculateFitCanvas,
|
|
|
MAX_CANVAS_SCALE,
|
|
|
@@ -152,6 +187,7 @@ import {
|
|
|
stepCanvasScale,
|
|
|
type CanvasScaleDirection
|
|
|
} from '@/components/mt-edit/utils/canvas-scale'
|
|
|
+import { shouldStartCanvasPan } from '@/components/mt-edit/utils/canvas-pan'
|
|
|
type MainPanelProps = {
|
|
|
groupEnabled: boolean
|
|
|
unGroupEnabled: boolean
|
|
|
@@ -167,6 +203,7 @@ const selectedAreaRef = ref<InstanceType<typeof SelectedArea>>()
|
|
|
const dragCanvasRef = ref<InstanceType<typeof DragCanvas>>()
|
|
|
const dragLineRenderRef = ref<InstanceType<typeof DrawLineRender>>()
|
|
|
const shortcut_drag_select_item_id = ref('')
|
|
|
+const panModeEnabled = ref(false)
|
|
|
// 是否需要重新计算画布缩放中心点
|
|
|
const is_need_recal_center = ref(true)
|
|
|
let is_listen_keydown = false // 是否已经监听了键盘事件
|
|
|
@@ -336,8 +373,19 @@ const onDragOver = (e: DragEvent) => {
|
|
|
const onRenderCoreMouseDown = (item: IDoneJson, e: MouseEvent) => {
|
|
|
commitActiveRightAsideEditor()
|
|
|
beginListenerKeyDown()
|
|
|
- if (isSystemShortcutKey(e)) {
|
|
|
- shortcut_drag_select_item_id.value = item.lock ? '' : item.id
|
|
|
+ const systemShortcutPressed = isSystemShortcutKey(e)
|
|
|
+ if (
|
|
|
+ shouldStartCanvasPan({
|
|
|
+ button: e.button,
|
|
|
+ panModeEnabled: panModeEnabled.value,
|
|
|
+ systemShortcutPressed,
|
|
|
+ canvasLocked: globalStore.lock
|
|
|
+ })
|
|
|
+ ) {
|
|
|
+ shortcut_drag_select_item_id.value =
|
|
|
+ systemShortcutPressed && !panModeEnabled.value && !globalStore.lock && !item.lock
|
|
|
+ ? item.id
|
|
|
+ : ''
|
|
|
beginDragCanvas(e)
|
|
|
return
|
|
|
}
|
|
|
@@ -384,17 +432,19 @@ const onRenderCoreMouseDown = (item: IDoneJson, e: MouseEvent) => {
|
|
|
const onMouseDown = (e: MouseEvent) => {
|
|
|
commitActiveRightAsideEditor()
|
|
|
beginListenerKeyDown()
|
|
|
- if (isSystemShortcutKey(e)) {
|
|
|
+ if (
|
|
|
+ shouldStartCanvasPan({
|
|
|
+ button: e.button,
|
|
|
+ panModeEnabled: panModeEnabled.value,
|
|
|
+ systemShortcutPressed: isSystemShortcutKey(e),
|
|
|
+ canvasLocked: globalStore.lock
|
|
|
+ })
|
|
|
+ ) {
|
|
|
shortcut_drag_select_item_id.value = ''
|
|
|
beginDragCanvas(e)
|
|
|
return
|
|
|
}
|
|
|
globalStore.cancelAllSelect()
|
|
|
- // 锁定状态或者右键点击进行画布拖动
|
|
|
- if (globalStore.lock || e.button == 2) {
|
|
|
- beginDragCanvas(e)
|
|
|
- return
|
|
|
- }
|
|
|
if (mainPanelProps.lineAppendEnable) {
|
|
|
globalStore.setIntention('drawSysLineStart')
|
|
|
const { realityX, realityY } = getRealityXY(e, canvasAreaRef.value?.getBoundingClientRect())
|
|
|
@@ -833,7 +883,6 @@ const dragCanvasMouseMove = (move_x: number, move_y: number) => {
|
|
|
const dragCanvasMouseUp = () => {
|
|
|
if (globalStore.intention == 'runDragCanvas') {
|
|
|
globalStore.setIntention('endDragCanvas')
|
|
|
- cacheStore.addHistory()
|
|
|
} else {
|
|
|
if (shortcut_drag_select_item_id.value) {
|
|
|
const find_item = globalStore.done_json.find(
|
|
|
@@ -1231,17 +1280,12 @@ const onKeydown = (e: KeyboardEvent) => {
|
|
|
cacheStore.addHistory()
|
|
|
}
|
|
|
}
|
|
|
-const updateCanvasScale = (scale: number, debounced = false) => {
|
|
|
+const updateCanvasScale = (scale: number) => {
|
|
|
const nextScale = normalizeCanvasScale(scale)
|
|
|
if (nextScale === globalStore.canvasCfg.scale) {
|
|
|
return false
|
|
|
}
|
|
|
globalStore.canvasCfg.scale = nextScale
|
|
|
- if (debounced) {
|
|
|
- cacheStore.addHistoryDebounced('canvas-scale')
|
|
|
- } else {
|
|
|
- cacheStore.addHistory()
|
|
|
- }
|
|
|
return true
|
|
|
}
|
|
|
const zoomCanvas = (direction: CanvasScaleDirection) => {
|
|
|
@@ -1273,7 +1317,6 @@ const fitCanvas = () => {
|
|
|
globalStore.canvasCfg.scale = fitResult.scale
|
|
|
globalStore.canvasCfg.transform_origin = fitResult.transformOrigin
|
|
|
globalStore.canvasCfg.drag_offset = fitResult.dragOffset
|
|
|
- cacheStore.addHistory()
|
|
|
}
|
|
|
const onMouseWheel = (e: WheelEvent) => {
|
|
|
if (isSystemShortcutKey(e)) {
|
|
|
@@ -1283,10 +1326,7 @@ const onMouseWheel = (e: WheelEvent) => {
|
|
|
if (!direction) {
|
|
|
return
|
|
|
}
|
|
|
- const didScale = updateCanvasScale(
|
|
|
- stepCanvasScale(globalStore.canvasCfg.scale, direction),
|
|
|
- true
|
|
|
- )
|
|
|
+ const didScale = updateCanvasScale(stepCanvasScale(globalStore.canvasCfg.scale, direction))
|
|
|
if (!didScale) {
|
|
|
return
|
|
|
}
|
|
|
@@ -1360,6 +1400,16 @@ defineExpose({
|
|
|
position: relative;
|
|
|
}
|
|
|
|
|
|
+.main-panel--pan-mode :deep(.canvasArea),
|
|
|
+.main-panel--pan-mode :deep(.canvasArea *) {
|
|
|
+ cursor: grab !important;
|
|
|
+}
|
|
|
+
|
|
|
+.main-panel--panning :deep(.canvasArea),
|
|
|
+.main-panel--panning :deep(.canvasArea *) {
|
|
|
+ cursor: grabbing !important;
|
|
|
+}
|
|
|
+
|
|
|
.canvasArea {
|
|
|
position: relative;
|
|
|
top: v-bind('globalStore.canvasCfg.drag_offset.y + "px"');
|
|
|
@@ -1405,6 +1455,19 @@ defineExpose({
|
|
|
padding: 0;
|
|
|
}
|
|
|
|
|
|
+.zoom-toolbar__modes {
|
|
|
+ display: flex;
|
|
|
+ padding: 2px;
|
|
|
+ background: #f2f4f7;
|
|
|
+ border-radius: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.zoom-toolbar__mode.is-active {
|
|
|
+ color: #fff;
|
|
|
+ background: var(--el-color-primary);
|
|
|
+ box-shadow: 0 2px 5px rgb(64 158 255 / 28%);
|
|
|
+}
|
|
|
+
|
|
|
.zoom-toolbar__icon:hover,
|
|
|
.zoom-toolbar__text:hover,
|
|
|
.zoom-toolbar__fit:hover {
|
|
|
@@ -1412,6 +1475,17 @@ defineExpose({
|
|
|
background: var(--el-color-primary-light-9);
|
|
|
}
|
|
|
|
|
|
+.zoom-toolbar__mode {
|
|
|
+ width: 30px;
|
|
|
+ min-width: 30px;
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.zoom-toolbar__mode.is-active:hover {
|
|
|
+ color: #fff;
|
|
|
+ background: var(--el-color-primary);
|
|
|
+}
|
|
|
+
|
|
|
.zoom-toolbar__value {
|
|
|
min-width: 52px;
|
|
|
font-size: 12px;
|