Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit adcf420

Browse files
feat: 拖拽组件部分完成
1 parent 852ea9b commit adcf420

File tree

5 files changed

+141
-40
lines changed

5 files changed

+141
-40
lines changed

‎src/utils/util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function onMove(callback: (event: MouseEvent) => void) {
3333
window.addEventListener('contextmenu', remove)
3434
window.addEventListener('mouseup', remove)
3535
function remove() {
36-
console.log('正在触发move事件')
36+
console.log('正在触发remove事件')
3737
window.removeEventListener('mousemove', moveEvent)
3838
window.removeEventListener('mouseup', remove)
3939
window.removeEventListener('mousemove', remove)

‎src/views/common/drag/components/DraggableBox.tsx

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ import styles from './draggable.module.scss'
33
import { useComponentStyle, usePointStyle } from '../hooks/useStyle'
44
import { AttrType } from '../types'
55
import { onMove } from '@/utils/util'
6+
import useMouse from '../hooks/useMouse'
67

78
interface DraggableBoxProps {
89
children: JSX.Element
910
attrs: AttrType
1011
active?: boolean
1112
scale?: number // 后续需要验证大于0
13+
parent?: boolean
1214
}
1315

1416
// 锚点
@@ -17,53 +19,24 @@ const pointList = ['t', 'r', 'b', 'l', 'lt', 'rt', 'lb', 'rb']
1719
const cursorResize = ['n', 'e', 's', 'w', 'nw', 'ne', 'sw', 'se']
1820

1921
const DraggableBox = (props: DraggableBoxProps) => {
20-
let remove = () => {}
21-
const [attrs, setAttrs] = useState(props.attrs)
22-
function onMouseDown(
23-
mouseDownEvent: any,
24-
point: string,
25-
attrs: AttrType,
26-
scale: number
27-
) {
28-
mouseDownEvent.stopPropagation()
29-
mouseDownEvent.preventDefault()
30-
const itemAttrX = attrs.x
31-
const itemAttrY = attrs.y
32-
const itemAttrW = attrs.w
33-
const itemAttrH = attrs.h
34-
// 记录点击初始位置
35-
const startX = mouseDownEvent.screenX
36-
const startY = mouseDownEvent.screenY
37-
remove = onMove((moveEvent) => {
38-
let currX = Math.round((moveEvent.screenX - startX) / scale)
39-
let currY = Math.round((moveEvent.screenY - startY) / scale)
40-
const isTop = /t/.test(point)
41-
const isBottom = /b/.test(point)
42-
const isLeft = /l/.test(point)
43-
const isRight = /r/.test(point)
44-
const newHeight = itemAttrH + (isTop ? -currY : isBottom ? currY : 0)
45-
const newWidth = itemAttrW + (isLeft ? -currX : isRight ? currX : 0)
46-
attrs.h = newHeight > 0 ? newHeight : 0
47-
attrs.w = newWidth > 0 ? newWidth : 0
48-
attrs.x = itemAttrX + (isLeft ? currX : 0)
49-
attrs.y = itemAttrY + (isTop ? currY : 0)
50-
setAttrs({ ...attrs })
51-
})
52-
}
53-
useEffect(() => {
54-
return () => remove()
55-
}, [])
22+
const { attrs, onPonitMouseHandle, onBoxMouseHandle, dragBoxRef } = useMouse(
23+
props.attrs,
24+
props.scale!,
25+
props.parent!
26+
)
5627
return (
5728
<div
29+
ref={dragBoxRef}
5830
className={styles.draggableBox}
31+
onMouseDown={onBoxMouseHandle}
5932
style={useComponentStyle(attrs, props.scale)}
6033
>
6134
{pointList.map((point, index) => {
6235
return (
6336
<div
6437
className={styles.draggablePoint + ' ' + styles[point]}
6538
key={point}
66-
onMouseDown={(e) => onMouseDown(e, point,attrs,props.scale!)}
39+
onMouseDown={(e) => onPonitMouseHandle(e, point)}
6740
style={usePointStyle(point, index, attrs, cursorResize)}
6841
></div>
6942
)
@@ -75,7 +48,8 @@ const DraggableBox = (props: DraggableBoxProps) => {
7548
}
7649
DraggableBox.defaultProps = {
7750
scale: 1,
78-
active: false
51+
active: false,
52+
parent: true
7953
}
8054

8155
export default DraggableBox

‎src/views/common/drag/dragPage.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.drag-parent {
2+
position: relative;
3+
width: 100%;
4+
height: 100%;
5+
background-image: linear-gradient(to right,
6+
rgba(0, 0, 0, .1) 1px,
7+
transparent 1px,
8+
transparent 10px),
9+
linear-gradient(to bottom,
10+
rgba(0, 0, 0, .1) 1px,
11+
transparent 1px,
12+
transparent 10px);
13+
background-size: 10px 10px;
14+
15+
}

‎src/views/common/drag/hooks/useMouse.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { useEffect, useRef, useState } from 'react'
2+
import { AttrType } from '../types'
3+
import { onMove } from '@/utils/util'
4+
5+
export default function useMouse(
6+
defaultAttrs: AttrType,
7+
scale: number,
8+
parent: boolean
9+
) {
10+
const [attrs, setAttrs] = useState(defaultAttrs)
11+
const dragBoxRef = useRef<HTMLDivElement | null>(null)
12+
let mouseEventRemove = () => {}
13+
function onPonitMouseHandle(mouseDownEvent: any, point: string) {
14+
mouseDownEvent.stopPropagation()
15+
mouseDownEvent.preventDefault()
16+
// 记录初始位置和大小
17+
const itemAttrX = attrs.x
18+
const itemAttrY = attrs.y
19+
const itemAttrW = attrs.w
20+
const itemAttrH = attrs.h
21+
// 记录点击初始位置
22+
const startX = mouseDownEvent.screenX
23+
const startY = mouseDownEvent.screenY
24+
const parentWidth = (dragBoxRef.current!.parentNode! as HTMLElement)
25+
.offsetWidth
26+
const parentHeight = (dragBoxRef.current!.parentNode! as HTMLElement)
27+
.offsetHeight
28+
mouseEventRemove = onMove((moveEvent) => {
29+
let currX = Math.round((moveEvent.screenX - startX) / scale)
30+
let currY = Math.round((moveEvent.screenY - startY) / scale)
31+
const isTop = /t/.test(point)
32+
const isBottom = /b/.test(point)
33+
const isLeft = /l/.test(point)
34+
const isRight = /r/.test(point)
35+
const newHeight = itemAttrH + (isTop ? -currY : isBottom ? currY : 0)
36+
const newWidth = itemAttrW + (isLeft ? -currX : isRight ? currX : 0)
37+
let h = newHeight > 0 ? newHeight : 0
38+
let w = newWidth > 0 ? newWidth : 0
39+
let x = itemAttrX + (isLeft ? currX : 0)
40+
let y = itemAttrY + (isTop ? currY : 0)
41+
42+
if (x > parentWidth - w) {
43+
w = Math.abs(parentWidth - x)
44+
x = parentWidth - w
45+
}
46+
if (x < 0) {
47+
w = w - Math.abs(x)
48+
x = 0
49+
}
50+
if (y > parentHeight - h) {
51+
h = Math.abs(parentHeight - y)
52+
y = parentHeight - h
53+
}
54+
if (y < 0) {
55+
h = h - Math.abs(y)
56+
y = 0
57+
}
58+
59+
setAttrs({ x, y, w, h })
60+
})
61+
}
62+
function onBoxMouseHandle(e: any, distance = 10) {
63+
e.preventDefault()
64+
e.stopPropagation()
65+
// 记录初始位置和大小
66+
const itemAttrX = attrs.x
67+
const itemAttrY = attrs.y
68+
const itemAttrW = attrs.w
69+
const itemAttrH = attrs.h
70+
// 记录点击初始位置
71+
const startX = e.screenX
72+
const startY = e.screenY
73+
const parentWidth = (dragBoxRef.current!.parentNode! as HTMLElement)
74+
.offsetWidth
75+
const parentHeight = (dragBoxRef.current!.parentNode! as HTMLElement)
76+
.offsetHeight
77+
mouseEventRemove = onMove((moveEvent) => {
78+
let currX = Math.round(itemAttrX + (moveEvent.screenX - startX) / scale)
79+
let currY = Math.round(itemAttrY + (moveEvent.screenY - startY) / scale)
80+
// 要预留的距离
81+
if (parent) {
82+
// 基于左上角位置检测
83+
currX = currX < 0 ? 0 : currX
84+
currY = currY < 0 ? 0 : currY
85+
// 基于右下角位置检测
86+
currX =
87+
currX > parentWidth - itemAttrW ? parentWidth - itemAttrW : currX
88+
currY =
89+
currY > parentHeight - itemAttrH ? parentHeight - itemAttrH : currY
90+
} else {
91+
// 基于左上角位置检测
92+
currX = currX < -itemAttrW + distance ? -itemAttrW + distance : currX
93+
currY = currY < -itemAttrH + distance ? -itemAttrH + distance : currY
94+
// 基于右下角位置检测
95+
currX = currX > parentWidth - distance ? parentWidth - distance : currX
96+
currY =
97+
currY > parentHeight - distance ? parentHeight - distance : currY
98+
}
99+
setAttrs({ ...attrs, x: currX, y: currY })
100+
})
101+
}
102+
useEffect(() => {
103+
return mouseEventRemove()
104+
})
105+
return {
106+
attrs,
107+
onPonitMouseHandle,
108+
onBoxMouseHandle,
109+
dragBoxRef
110+
}
111+
}

‎src/views/common/drag/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React from 'react'
22
import DraggableBox from './components/DraggableBox'
3+
import './dragPage.scss'
34
const CommonDrag = () => {
45
return (
56
<div className="page-container">
6-
<div style={{position: 'relative'}}>
7+
<div className="drag-parent">
78
<DraggableBox
89
attrs={{
910
w: 200,

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /