@@ -37,6 +37,9 @@ export const useDrag = ({
37
37
let startY = 0 ;
38
38
let initialX = 10 ;
39
39
let initialY = 10 ;
40
+ // 鼠标位置
41
+ let mouseX = 0 ;
42
+ let mouseY = 0 ;
40
43
// 是否是一个有效的拖拽
41
44
let dragEffect = false ;
42
45
// 拖拽线前后元素的最小层级,用来生成层级分段
@@ -86,6 +89,7 @@ export const useDrag = ({
86
89
87
90
// 找到目标元素 virt-tree-item
88
91
let scrollElementRect : DOMRect | undefined = undefined ;
92
+ let clientElementRect : DOMRect | undefined = undefined ;
89
93
90
94
const dragBox = document . createElement ( 'div' ) ;
91
95
dragBox . classList . add ( 'virt-tree-drag-box' ) ;
@@ -108,23 +112,29 @@ export const useDrag = ({
108
112
event . preventDefault ( ) ;
109
113
event . stopPropagation ( ) ;
110
114
115
+ const clientElement = virtListRef . value ?. $el ;
116
+ clientElementRect = clientElement ?. getBoundingClientRect ( ) ;
117
+ scrollElement = getScrollParentElement ( clientElement ) ;
118
+ scrollElementRect = scrollElement ?. getBoundingClientRect ( ) ;
119
+ // console.log('scrollElement', scrollElement);
120
+
121
+ scrollElement ?. addEventListener ( 'scroll' , onScroll ) ;
111
122
document . addEventListener ( 'mousemove' , onMousemove ) ;
112
123
document . addEventListener ( 'mouseup' , onMouseup ) ;
113
124
document . addEventListener ( 'keydown' , onKeydown ) ;
114
125
}
115
126
127
+ function onScroll ( ) {
128
+ if ( dragging . value ) {
129
+ dragProcess ( ) ;
130
+ }
131
+ }
132
+
116
133
function dragstart ( ) {
117
134
if ( ! sourceTreeItem ) return ;
118
- // 拿到treeNode后生成一个一样的元素用来拖拽
119
- const clientElement = virtListRef . value ?. $el ;
120
- scrollElement = getScrollParentElement ( clientElement ) ;
121
- scrollElementRect = scrollElement ?. getBoundingClientRect ( ) ;
122
- // console.log('scrollElement', scrollElement);
123
-
124
135
// 找到目标元素的virt-tree-node,判断是否展开状态,如果是,则定时1s后折叠
125
136
// 数据&交互处理
126
137
const nodeKey = sourceTreeItem ?. dataset ?. id ?? '' ;
127
- // if (treeInfo && nodeKey) {
128
138
sourceNode = getTreeNode ( nodeKey ) ;
129
139
if ( ! sourceNode ) return ;
130
140
@@ -161,29 +171,64 @@ export const useDrag = ({
161
171
162
172
return cloneTreeItem ;
163
173
}
164
- function onMousemove ( event : MouseEvent ) {
165
- if ( ! cloneTreeItem ) {
166
- dragstart ( ) ;
167
- }
168
- if ( ! cloneTreeItem ) return ;
169
174
170
- dragging . value = true ;
175
+ // 自动滚动
176
+ function autoScroll ( ) {
177
+ if ( scrollElement !== null && scrollElementRect !== undefined ) {
178
+ // 每次先清除旧定时器
179
+ if ( autoScrollTimer ) {
180
+ clearInterval ( autoScrollTimer ) ;
181
+ autoScrollTimer = null ;
182
+ }
183
+ // 判断是否在可视区域
184
+ if ( clientElementRect ) {
185
+ if (
186
+ mouseX < clientElementRect . left ||
187
+ mouseX > clientElementRect . right ||
188
+ mouseY < clientElementRect . top ||
189
+ mouseY > clientElementRect . bottom
190
+ ) {
191
+ return ;
192
+ }
193
+ }
194
+ // 4等分
195
+ const equalPart = scrollElementRect . height / 4 ;
196
+ const multiple = 20 ;
197
+ if (
198
+ scrollElementRect . top < mouseY &&
199
+ mouseY < scrollElementRect . top + equalPart
200
+ ) {
201
+ const relative =
202
+ ( 1 - ( mouseY - scrollElementRect . top ) / equalPart ) * multiple ;
203
+ if ( ! autoScrollTimer ) {
204
+ autoScrollTimer = setInterval ( ( ) => {
205
+ scrollElement ! . scrollTop -= relative ;
206
+ } , 10 ) ;
207
+ }
208
+ } else if (
209
+ scrollElementRect . top + equalPart * 3 < mouseY &&
210
+ mouseY < scrollElementRect . bottom
211
+ ) {
212
+ const relative =
213
+ ( ( mouseY - ( scrollElementRect . top + equalPart * 3 ) ) / equalPart ) *
214
+ multiple ;
215
+ if ( ! autoScrollTimer ) {
216
+ autoScrollTimer = setInterval ( ( ) => {
217
+ scrollElement ! . scrollTop += relative ;
218
+ } , 10 ) ;
219
+ }
220
+ }
221
+ }
222
+ }
171
223
172
- const clientX = event . clientX ;
173
- const clientY = event . clientY ;
174
- const dx = clientX - startX ;
175
- const dy = clientY - startY ;
176
- cloneTreeItem . style . left = `${ initialX + dx } px` ;
177
- cloneTreeItem . style . top = `${ initialY + dy } px` ;
178
- const clientElement = virtListRef . value ?. $el ;
179
- const clientElementRect = clientElement ?. getBoundingClientRect ( ) ;
224
+ function dragProcess ( ) {
225
+ // 判断是否在可视区域,不在则移除
180
226
if ( clientElementRect ) {
181
- // 不在可视区域,移除
182
227
if (
183
- clientX < clientElementRect . left ||
184
- clientX > clientElementRect . right ||
185
- clientY < clientElementRect . top ||
186
- clientY > clientElementRect . bottom
228
+ mouseX < clientElementRect . left ||
229
+ mouseX > clientElementRect . right ||
230
+ mouseY < clientElementRect . top ||
231
+ mouseY > clientElementRect . bottom
187
232
) {
188
233
// 移除 line
189
234
if ( hasStyleTreeItem ?. contains ( dragLine ) ) {
@@ -199,32 +244,10 @@ export const useDrag = ({
199
244
}
200
245
}
201
246
202
- if ( scrollElement && scrollElementRect ) {
203
- // 自动滚动
204
- if ( clientY > scrollElementRect . bottom ) {
205
- if ( ! autoScrollTimer ) {
206
- autoScrollTimer = setInterval ( ( ) => {
207
- scrollElement ! . scrollTop += 2 ;
208
- } , 10 ) ;
209
- }
210
- } else if ( clientY < scrollElementRect . top ) {
211
- if ( ! autoScrollTimer ) {
212
- autoScrollTimer = setInterval ( ( ) => {
213
- scrollElement ! . scrollTop -= 2 ;
214
- } , 10 ) ;
215
- }
216
- } else {
217
- if ( autoScrollTimer ) {
218
- clearInterval ( autoScrollTimer ) ;
219
- autoScrollTimer = null ;
220
- }
221
- }
222
- }
223
-
224
- const hoverElement = document . elementFromPoint ( clientX , clientY ) ;
247
+ // 获取hover元素
248
+ const hoverElement = document . elementFromPoint ( mouseX , mouseY ) ;
225
249
if ( ! hoverElement ) return ;
226
250
hoverTreeItem = findAncestorWithClass ( hoverElement , 'virt-tree-item' ) ;
227
-
228
251
if ( ! hoverTreeItem ) {
229
252
return ;
230
253
}
@@ -252,7 +275,6 @@ export const useDrag = ({
252
275
253
276
const elementTop = hoverTreeItemRect . top ;
254
277
const elementHeight = hoverTreeItemRect . height ;
255
- const mouseY = event . clientY ;
256
278
// 鼠标相对于元素顶部的距离
257
279
const relativeY = mouseY - elementTop ;
258
280
// 计算鼠标相对于元素高度的比例
@@ -408,7 +430,7 @@ export const useDrag = ({
408
430
409
431
if ( placement !== 'center' ) {
410
432
// 需要减去第一个indent
411
- const relativeX = clientX - hoverTreeItemRect . left - props . indent ;
433
+ const relativeX = mouseX - hoverTreeItemRect . left - props . indent ;
412
434
targetLevel = Math . ceil ( relativeX / props . indent ) ;
413
435
if ( targetLevel <= minLevel ) targetLevel = minLevel ;
414
436
if ( targetLevel >= maxLevel ) targetLevel = maxLevel ;
@@ -425,6 +447,27 @@ export const useDrag = ({
425
447
}
426
448
}
427
449
}
450
+
451
+ function onMousemove ( event : any ) {
452
+ if ( ! cloneTreeItem ) {
453
+ dragstart ( ) ;
454
+ }
455
+ if ( ! cloneTreeItem ) return ;
456
+
457
+ dragging . value = true ;
458
+
459
+ mouseX = event . clientX ;
460
+ mouseY = event . clientY ;
461
+ const dx = mouseX - startX ;
462
+ const dy = mouseY - startY ;
463
+ cloneTreeItem . style . left = `${ initialX + dx } px` ;
464
+ cloneTreeItem . style . top = `${ initialY + dy } px` ;
465
+
466
+ autoScroll ( ) ;
467
+
468
+ dragProcess ( ) ;
469
+ }
470
+
428
471
function onMouseup ( ) {
429
472
if ( dragging . value ) {
430
473
// 延迟一下,不然click仍然会被触发
@@ -521,6 +564,7 @@ export const useDrag = ({
521
564
sourceTreeItem = null ;
522
565
}
523
566
567
+ scrollElement ?. removeEventListener ( 'scroll' , onScroll ) ;
524
568
document . removeEventListener ( 'mousemove' , onMousemove ) ;
525
569
document . removeEventListener ( 'mouseup' , onMouseup ) ;
526
570
}
0 commit comments