Преглед на файлове

feat: 添加鼠标左键移动画布

jiaxing.liao преди 2 седмици
родител
ревизия
3425ac3a64

+ 26 - 4
src/renderer/src/views/designer/workspace/stage/DesignerCanvas.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="stage-wrapper" ref="stageWrapperRef" :style="getWrapperStyle">
+  <div class="stage-wrapper" ref="stageWrapperRef" :style="getWrapperStyle" @wheel="handleWheel">
     <div class="stage" ref="stageRef" :style="getStyles.stageStyle">
       <div ref="tipRef" class="tip-txt" :style="getStyles.tipStyle">
         {{ screen?.name }}:{{ page?.name }}
@@ -34,7 +34,6 @@
 </template>
 
 <script setup lang="ts">
-import type { Ref } from 'vue'
 import type { StageState } from './type'
 import type { Page } from '@/types/page'
 import type { Screen } from '@/types/screen'
@@ -42,6 +41,8 @@ import type { Screen } from '@/types/screen'
 import { ref, onMounted, computed, nextTick } from 'vue'
 import { useScroll, useElementSize } from '@vueuse/core'
 import { useProjectStore } from '@/store/modules/project'
+import { useCanvasMove } from './useCanvasMove'
+import { throttle } from 'lodash-es'
 
 import Nodes from './Node.vue'
 import Moveable from './Moveable.vue'
@@ -54,11 +55,13 @@ const props = defineProps<{
 const emit = defineEmits<{
   changeState: [Partial<StageState>]
 }>()
-const stageWrapperRef: Ref<HTMLElement | null> = ref(null)
-const canvasRef: Ref<HTMLElement | null> = ref(null)
+const stageWrapperRef = ref<HTMLDivElement>()
+const canvasRef = ref<HTMLDivElement>()
 const { width: clientWidth, height: clientHeight } = useElementSize(stageWrapperRef)
 const projectStore = useProjectStore()
 
+useCanvasMove(stageWrapperRef, props.state)
+
 const getWrapperStyle = computed(() => {
   const { showRuler } = props.state
   return {
@@ -138,6 +141,9 @@ const getStyles = computed(() => {
   }
 })
 
+/**
+ * 监听滚动 更新标尺
+ */
 useScroll(stageWrapperRef, {
   throttle: 0,
   onScroll: () => {
@@ -193,6 +199,22 @@ const initStagePosition = async () => {
   stageWrapperRef.value!.scrollTo(centerX, centerY)
 }
 
+/**
+ * 滚动缩放处理
+ * Ctrl + 鼠标滚轮缩放
+ */
+const handleWheel = throttle((e: WheelEvent) => {
+  if (e.ctrlKey) {
+    const { state } = props
+    //滚轮方向
+    const direction = e.deltaY > 0 ? 'down' : 'up'
+    const scale = direction === 'up' ? state.scale + 0.05 : state.scale - 0.05
+    emit('changeState', {
+      scale: scale < 0.1 ? 0.1 : scale > 4 ? 4 : scale
+    })
+  }
+}, 16)
+
 defineExpose({
   getPosition: () => canvasRef.value?.getBoundingClientRect(),
   initScale,

+ 13 - 10
src/renderer/src/views/designer/workspace/stage/index.vue

@@ -211,16 +211,19 @@ const handleMouseDown = (e: MouseEvent) => {
     return
   }
 
-  const { top, left } = boxRef.value!.getBoundingClientRect()
-  const { clientX, clientY } = e
-  isMouseDown.value = true
-  workspaceLeft = left
-  workspaceTop = top
-  startX = clientX - left
-  startY = clientY - top
-  selectBoxRef.value!.style.display = 'block'
-  selectBoxRef.value!.style.left = `${startX}px`
-  selectBoxRef.value!.style.top = `${startY}px`
+  // 按住ctrl键时开启框选
+  if (e.ctrlKey) {
+    const { top, left } = boxRef.value!.getBoundingClientRect()
+    const { clientX, clientY } = e
+    isMouseDown.value = true
+    workspaceLeft = left
+    workspaceTop = top
+    startX = clientX - left
+    startY = clientY - top
+    selectBoxRef.value!.style.display = 'block'
+    selectBoxRef.value!.style.left = `${startX}px`
+    selectBoxRef.value!.style.top = `${startY}px`
+  }
 }
 /* 鼠标移动 */
 const handleMouseMove = throttle((e: MouseEvent) => {

+ 65 - 0
src/renderer/src/views/designer/workspace/stage/useCanvasMove.ts

@@ -0,0 +1,65 @@
+import type { Ref } from 'vue'
+import type { StageState } from './type'
+
+import { useEventListener } from 'vue-hooks-plus'
+import { throttle } from 'lodash-es'
+
+/**
+ * 处理画布移动方法
+ * @param element 画布元素
+ */
+export const useCanvasMove = (element: Ref<HTMLDivElement | undefined>, state: StageState) => {
+  let flag = false
+  /**
+   * 鼠标按下事件
+   */
+  const onMouseDown = (e: MouseEvent) => {
+    const target = e?.target as Element | null
+    if (
+      target?.closest('.stage-title') ||
+      target?.closest('.edit-box') ||
+      target?.closest('.component-content') ||
+      target?.closest('.component-wrapper') ||
+      target?.closest('.scaleplate-horizontal') ||
+      target?.closest('.scaleplate-vertical') ||
+      target?.closest('.refer-line-img') ||
+      target?.closest('.workspace-bottom') ||
+      target?.closest('.refer-line') ||
+      target?.closest('.ignore-click') ||
+      target?.closest('.moveable-area') ||
+      target?.closest('.moveable-control') ||
+      target?.closest('.moveable-edge')
+    ) {
+      return
+    }
+
+    // 当前未按下ctrl且是鼠标左键
+    if (!e.ctrlKey && e.button === 0) {
+      flag = true
+    } else {
+      flag = false
+    }
+  }
+
+  /**
+   * 鼠标移动事件
+   */
+  const onMouseMove = (e: MouseEvent) => {
+    if (flag) {
+      const moveX = -e.movementX * (2 - state.scale)
+      const moveY = -e.movementY * (2 - state.scale)
+      element.value?.scrollBy(moveX, moveY)
+    }
+  }
+
+  /**
+   * 鼠标抬起事件
+   */
+  const onMouseUp = () => {
+    flag = false
+  }
+
+  useEventListener('mousedown', throttle(onMouseDown, 10), { target: element })
+  useEventListener('mousemove', throttle(onMouseMove, 10), { target: element })
+  useEventListener('mouseup', throttle(onMouseUp, 10), { target: element })
+}