Skip to content

Commit da6e86b

Browse files
committed
fix: adapt multi-node-drag
1 parent f5707c3 commit da6e86b

6 files changed

Lines changed: 1070 additions & 31 deletions

File tree

packages/canvas/container/src/CanvasContainer.vue

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,18 @@
88
:windowGetClickEventTarget="target"
99
:resize="canvasState.type === 'absolute'"
1010
:multiStateLength="multiStateLength"
11+
:isMultiDragging="isMultiDragging()"
1112
@select-slot="selectSlot"
1213
@setting="settingModel"
1314
></canvas-action>
1415
</div>
16+
<canvas-multi-drag-indicator
17+
:lineState="lineState"
18+
:multiDragState="multiDragState"
19+
:multiStateLength="multiStateLength"
20+
:isMultiDragging="isMultiDragging()"
21+
:getMultiDragPositionText="getMultiDragPositionText"
22+
></canvas-multi-drag-indicator>
1523
<canvas-router-jumper :hoverState="hoverState" :inactiveHoverState="inactiveHoverState"></canvas-router-jumper>
1624
<canvas-viewer-switcher :hoverState="hoverState" :inactiveHoverState="inactiveHoverState"></canvas-viewer-switcher>
1725
<canvas-divider :selectState="computedSelectState"></canvas-divider>
@@ -62,7 +70,9 @@ import CanvasViewerSwitcher from './components/CanvasViewerSwitcher.vue'
6270
import CanvasResize from './components/CanvasResize.vue'
6371
import CanvasDivider from './components/CanvasDivider.vue'
6472
import CanvasResizeBorder from './components/CanvasResizeBorder.vue'
73+
import CanvasMultiDragIndicator from './components/CanvasMultiDragIndicator.vue'
6574
import { useMultiSelect } from './composables/useMultiSelect'
75+
import { useMultiDrag } from './composables/useMultiDrag'
6676
import {
6777
canvasState,
6878
onMouseUp,
@@ -92,7 +102,8 @@ export default {
92102
CanvasDivider,
93103
CanvasResizeBorder,
94104
CanvasRouterJumper,
95-
CanvasViewerSwitcher
105+
CanvasViewerSwitcher,
106+
CanvasMultiDragIndicator
96107
},
97108
props: {
98109
controller: Object,
@@ -113,9 +124,11 @@ export default {
113124
const containerPanel = ref(null)
114125
const insertContainer = ref(false)
115126
116-
const { multiSelectedStates } = useMultiSelect()
127+
const { multiSelectedStates, isMouseDown } = useMultiSelect()
117128
118129
const multiStateLength = computed(() => multiSelectedStates.value.length)
130+
const { startMultiDrag, moveMultiDrag, endMultiDrag, isMultiDragging, getMultiDragPositionText, multiDragState } =
131+
useMultiDrag()
119132
120133
const computedSelectState = computed(() => {
121134
if (multiSelectedStates.value.length === 1) {
@@ -129,6 +142,15 @@ export default {
129142
const { clientX, clientY } = event
130143
const element = getElement(event.target)
131144
closeMenu()
145+
146+
if (!element) return
147+
148+
// 优先处理右键菜单
149+
if (event.button === 2) {
150+
openMenu(event)
151+
return
152+
}
153+
132154
let node = getCurrent().schema
133155
134156
if (element) {
@@ -144,15 +166,17 @@ export default {
144166
}
145167
}
146168
147-
if (event.button === 0 && element !== element.ownerDocument.body) {
148-
const { x, y } = element.getBoundingClientRect()
149-
150-
dragStart(node, element, { offsetX: clientX - x, offsetY: clientY - y })
169+
// 处理多选拖拽开始 - 确保在单节点拖拽之前处理
170+
if (startMultiDrag(event, element)) {
171+
return
151172
}
152173
153-
// 如果是点击右键则打开右键菜单
154-
if (event.button === 2) {
155-
openMenu(event)
174+
// 处理单节点拖拽开始
175+
if (event.button === 0 && element !== element.ownerDocument.body) {
176+
const { x, y } = element.getBoundingClientRect()
177+
if (multiStateLength.value === 1) {
178+
dragStart(node, element, { offsetX: clientX - x, offsetY: clientY - y })
179+
}
156180
}
157181
}
158182
}
@@ -206,9 +230,10 @@ export default {
206230
const doc = iframe.value.contentDocument
207231
const win = iframe.value.contentWindow
208232
233+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
209234
let isScrolling = false
210235
211-
// 以下是内部iframe监听的事件
236+
// 监听鼠标按下事件
212237
win.addEventListener('mousedown', (event) => {
213238
handleCanvasEvent(() => {
214239
// html元素使用scroll和mouseup事件处理
@@ -222,6 +247,8 @@ export default {
222247
return
223248
}
224249
250+
isMouseDown.value = true
251+
225252
insertPosition.value = false
226253
insertContainer.value = false
227254
setCurrentNode(event)
@@ -235,32 +262,49 @@ export default {
235262
isScrolling = true
236263
})
237264
238-
win.addEventListener('mouseup', (event) => {
239-
if (event.target !== doc.documentElement || isScrolling) {
240-
return
241-
}
265+
// 监听鼠标移动事件
266+
win.addEventListener('mousemove', (ev) => {
267+
handleCanvasEvent(() => {
268+
// 优先处理多选拖拽移动
269+
if (!moveMultiDrag(ev)) {
270+
// 如果不是多选拖拽,则处理普通拖拽
271+
dragMove(ev, true)
272+
}
273+
})
274+
})
275+
276+
// 监听拖拽结束事件
277+
win.addEventListener('mouseup', (ev) => {
278+
handleCanvasEvent(() => {
279+
if (ev.button === 0 && isMouseDown.value) {
280+
isMouseDown.value = false
281+
}
242282
243-
insertPosition.value = false
244-
insertContainer.value = false
245-
setCurrentNode(event)
246-
target.value = event.target
283+
// 优先处理多选拖拽结束
284+
if (!endMultiDrag()) {
285+
// 如果不是多选拖拽,则处理普通拖拽结束
286+
onMouseUp(ev)
287+
}
288+
})
247289
})
248290
291+
// 监听拖拽过程事件
249292
win.addEventListener('dragover', (ev) => {
250293
ev.dataTransfer.dropEffect = 'move'
251294
ev.preventDefault()
252-
dragMove(ev)
295+
// 优先处理多选拖拽移动
296+
if (!moveMultiDrag(ev)) {
297+
dragMove(ev)
298+
}
253299
})
254300
301+
// 监听放置事件
255302
win.addEventListener('drop', (ev) => {
256303
ev.preventDefault()
257-
onMouseUp(ev)
258-
})
259-
260-
win.addEventListener('mousemove', (ev) => {
261-
handleCanvasEvent(() => {
262-
dragMove(ev, true)
263-
})
304+
// 优先处理多选拖拽结束
305+
if (!endMultiDrag()) {
306+
onMouseUp(ev)
307+
}
264308
})
265309
266310
// 阻止浏览器默认的右键菜单功能
@@ -327,6 +371,7 @@ export default {
327371
document.addEventListener('canvasReady', canvasReady)
328372
329373
return {
374+
isMouseDown,
330375
iframe,
331376
dragState,
332377
hoverState,
@@ -347,7 +392,10 @@ export default {
347392
insertPosition,
348393
insertContainer,
349394
loading,
350-
srcAttrName
395+
srcAttrName,
396+
isMultiDragging,
397+
multiDragState,
398+
getMultiDragPositionText
351399
}
352400
}
353401
}

packages/canvas/container/src/components/CanvasAction.vue

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div
33
v-show="selectState.height && selectState.width"
4-
class="canvas-rect select"
4+
:class="['canvas-rect select', { 'multi-select': multiStateLength > 1 }, { dragging: isMultiDragging }]"
55
:style="{
66
top: selectState.top + 'px',
77
left: selectState.left + 'px',
@@ -189,6 +189,10 @@ export default {
189189
type: Boolean,
190190
default: false
191191
},
192+
isMultiDragging: {
193+
type: Boolean,
194+
default: false
195+
},
192196
windowGetClickEventTarget: Object
193197
},
194198
emits: ['remove', 'selectSlot', 'setting'],
@@ -716,7 +720,59 @@ export default {
716720
}
717721
}
718722
}
723+
724+
&.multi-select {
725+
border-color: var(--te-canvas-container-border-color-checked);
726+
border-style: solid;
727+
border-width: 2px;
728+
729+
.corner-mark-left {
730+
background-color: var(--te-canvas-container-bg-color-checked);
731+
color: var(--te-canvas-container-text-color-white);
732+
}
733+
734+
&.dragging {
735+
opacity: 0.7;
736+
border-color: var(--te-canvas-container-border-color-multi, #1890ff);
737+
border-style: dashed;
738+
border-width: 2px;
739+
background-color: rgba(24, 144, 255, 0.15);
740+
box-shadow: 0 0 12px rgba(24, 144, 255, 0.4);
741+
transition: all 0.2s ease;
742+
animation: pulse-border 1.5s infinite;
743+
744+
.corner-mark-left {
745+
background-color: var(--te-canvas-container-border-color-multi, #1890ff);
746+
animation: pulse-bg 1.5s infinite;
747+
}
748+
}
749+
}
750+
}
751+
752+
@keyframes pulse-border {
753+
0% {
754+
box-shadow: 0 0 0 0 rgba(24, 144, 255, 0.4);
755+
}
756+
70% {
757+
box-shadow: 0 0 0 6px rgba(24, 144, 255, 0);
758+
}
759+
100% {
760+
box-shadow: 0 0 0 0 rgba(24, 144, 255, 0);
761+
}
719762
}
763+
764+
@keyframes pulse-bg {
765+
0% {
766+
background-color: rgba(24, 144, 255, 1);
767+
}
768+
50% {
769+
background-color: rgba(24, 144, 255, 0.7);
770+
}
771+
100% {
772+
background-color: rgba(24, 144, 255, 1);
773+
}
774+
}
775+
720776
.short-cut-set.short-cut-set.tiny-popper.tiny-popover {
721777
.tiny-popover__title {
722778
color: var(--te-canvas-container-text-color-primary);

0 commit comments

Comments
 (0)