瀏覽代碼

feat: 新增框选功能

奔跑的面条 3 年之前
父節點
當前提交
33ed0fa468

+ 7 - 6
src/views/chart/ContentEdit/components/EditSelect/index.vue

@@ -26,6 +26,7 @@ watch(
   positionInfo => {
     if (!isSelect.value) return
 
+    // 这里的 x,y 是已经计算过的相对位移值
     const { startX, startY, x, y } = positionInfo
 
     const attr = {
@@ -42,25 +43,25 @@ watch(
 
     // 处理位置
     if (x > startX && y > startY) {
-      // 右下
+      // 右下方向
       attr.x = startX
       attr.y = startY
       attr.w = Math.round((x - startX) / scale.value)
       attr.h = Math.round((y - startY) / scale.value)
     } else if (x > startX && y < startY) {
-      // 右上
+      // 右上方向
       attr.x = startX
       attr.w = Math.round((x - startX) / scale.value)
       attr.h = Math.round((startY - y) / scale.value)
       attr.y = startY - attr.h
     } else if (x < startX && y > startY) {
-      // 左下
+      // 左下方向
       attr.y = startY
       attr.w = Math.round((startX - x) / scale.value)
       attr.h = Math.round((y - startY) / scale.value)
       attr.x = startX - attr.w
     } else {
-      // 左上
+      // 左上方向
       attr.w = Math.round((startX - x) / scale.value)
       attr.h = Math.round((startY - y) / scale.value)
       attr.x = startX - attr.w
@@ -92,7 +93,7 @@ watch(
   .select-border {
     left: 0;
     top: 0;
-    opacity: 1;
+    opacity: 0.5;
     border-width: 2px;
     border-style: solid;
     border-color: v-bind('themeColor');
@@ -100,7 +101,7 @@ watch(
   .select-background {
     top: 2px;
     left: 2px;
-    opacity: 0.1;
+    opacity: 0.03;
     background-color: v-bind('themeColor');
   }
 }

+ 75 - 3
src/views/chart/ContentEdit/hooks/useDrag.hook.ts

@@ -70,15 +70,83 @@ export const mousedownBoxSelect = (e: MouseEvent, item?: CreateComponentType | C
   const startScreenX = e.screenX
   const startScreenY = e.screenY
 
+  // 记录缩放
+  const scale = chartEditStore.getEditCanvas.scale
+
   chartEditStore.setMousePosition(undefined, undefined, startOffsetX, startOffsetY)
 
   // 移动框选
   const mousemove = throttle((moveEvent: MouseEvent) => {
+    // 取消当前选中
+    chartEditStore.setTargetSelectChart()
+    chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_SELECT, true)
+
+    // 这里先把相对值算好,不然组件无法获取 startScreenX 和 startScreenY 的值
     const currX = startOffsetX + moveEvent.screenX - startScreenX
     const currY = startOffsetY + moveEvent.screenY - startScreenY
-
-    chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_SELECT, true)
     chartEditStore.setMousePosition(currX, currY)
+
+    // 计算框选的左上角和右下角
+    const selectAttr = {
+      // 左上角
+      x1: 0,
+      y1: 0,
+      // 右下角
+      x2: 0,
+      y2: 0
+    }
+    if (currX > startOffsetX && currY > startOffsetY) {
+      // 右下方向
+      selectAttr.x1 = startOffsetX
+      selectAttr.y1 = startOffsetY
+      selectAttr.x2 = Math.round(startOffsetX + (moveEvent.screenX - startScreenX) / scale)
+      selectAttr.y2 = Math.round(startOffsetY + (moveEvent.screenY - startScreenY) / scale)
+    } else if (currX > startOffsetX && currY < startOffsetY) {
+      // 右上方向
+      selectAttr.x1 = startOffsetX
+      selectAttr.y1 = Math.round(startOffsetY - (startScreenY - moveEvent.screenY) / scale)
+      selectAttr.x2 = Math.round(startOffsetX + (moveEvent.screenX - startScreenX) / scale)
+      selectAttr.y2 = startOffsetY
+    } else if (currX < startOffsetX && currY > startOffsetY) {
+      selectAttr.x1 = Math.round(startOffsetX - (startScreenX - moveEvent.screenX) / scale)
+      selectAttr.y1 = startOffsetY
+      selectAttr.x2 = startOffsetX
+      selectAttr.y2 = Math.round(startOffsetY + (moveEvent.screenY - startScreenY ) / scale)
+      // 左下方向
+    } else {
+      // 左上方向
+      selectAttr.x1 = Math.round(startOffsetX - (startScreenX - moveEvent.screenX) / scale)
+      selectAttr.y1 = Math.round(startOffsetY - (startScreenY - moveEvent.screenY) / scale)
+      selectAttr.x2 = startOffsetX
+      selectAttr.y2 = startOffsetY
+    }
+
+    // 遍历组件
+    chartEditStore.getComponentList.forEach(item => {
+      if (!chartEditStore.getTargetChart.selectId.includes(item.id)) {
+        // 处理左上角
+        let isSelect = false
+        const { x, y, w, h } = item.attr
+        const targetAttr = {
+          // 左上角
+          x1: x,
+          y1: y,
+          // 右下角
+          x2: x + w,
+          y2: y + h
+        }
+        // 全包含则选中
+        if (
+          targetAttr.x1 - selectAttr.x1 >= 0 &&
+          targetAttr.y1 - selectAttr.y1 >= 0 &&
+          targetAttr.x2 - selectAttr.x2 <= 0 &&
+          targetAttr.y2 - selectAttr.y2 <= 0
+        ) {
+          isSelect = true
+          chartEditStore.setTargetSelectChart(item.id, true)
+        }
+      }
+    })
   }, 50)
 
   // 鼠标抬起
@@ -159,6 +227,7 @@ export const useMouseHandle = () => {
 
     // 移动-计算偏移量
     const mousemove = throttle((moveEvent: MouseEvent) => {
+      chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, true)
       chartEditStore.setMousePosition(moveEvent.screenX, moveEvent.screenY)
 
       // 当前偏移量,处理 scale 比例问题
@@ -197,6 +266,7 @@ export const useMouseHandle = () => {
 
     const mouseup = () => {
       chartEditStore.setMousePosition(0, 0, 0, 0)
+      chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, false)
       document.removeEventListener('mousemove', mousemove)
       document.removeEventListener('mouseup', mouseup)
     }
@@ -209,7 +279,9 @@ export const useMouseHandle = () => {
   const mouseenterHandle = (e: MouseEvent, item: CreateComponentType | CreateComponentGroupType) => {
     e.preventDefault()
     e.stopPropagation()
-    chartEditStore.setTargetHoverChart(item.id)
+    if (!chartEditStore.getEditCanvas.isSelect) {
+      chartEditStore.setTargetHoverChart(item.id)
+    }
   }
 
   // * 移出事件