Skip to main content

react鼠标拖拽交互

import { Dropdown, Menu } from 'antd'
import { useState } from 'react'

interface Props {
measure: {
leftWidth: number
rightWidth: number
widthOfMinute: number
minuteOfWidth: number
}
}

const AreaBar = (props: Props) => {
const {
measure
} = props

const [left, setLeft] = useState<number>(200)
const [width, setWidth] = useState<number>(200)

const hourWidth = measure.widthOfMinute * 60
const twoHoursWidth = measure.widthOfMinute * 120

const contextMenu = (
<Menu items={[
{
key: 'edit',
label: (
<div>编辑</div>
),
},
{
key: 'delete',
label: (
<div>删除</div>
),
}
]} />
)

// 拖动
const handleMouseDown = (e: any) => {
const startX = e.clientX
let _left = left
document.onmousemove = (e2: any) => {
const endX = e2.clientX
const diffX = endX - startX
_left = left + diffX
// 左限
if(_left <= 0) {
_left = 0
}
// 右限
if(_left >= (measure.rightWidth - width)) {
_left = measure.rightWidth - width
}
setLeft(_left)
}
document.onmouseup = () => {
document.onmousemove = null
document.onmouseup = null
// 吸附
const newLeft = Math.floor(_left / hourWidth) * hourWidth
// const newWidth = Math.ceil((_left + width) / hourWidth) * hourWidth - newLeft // 左右吸附
const newWidth = Math.floor((_left + width) / hourWidth) * hourWidth - newLeft // 左吸附
setLeft(newLeft)
setWidth(newWidth)
}
}

// 左拉伸
const handleLeftMouseDown = (e: any) => {
const startX = e.clientX
const maxWidth = width + left
const minLeft = maxWidth - hourWidth
let _left = left
document.onmousemove = (e2: any) => {
const endX = e2.clientX
const diffX = endX - startX
_left = left + diffX
let _width = width - diffX
// 左限
if(_left <= 0) {
_left = 0
_width = maxWidth
}
// 右限
if(_width <= hourWidth) {
_width = hourWidth
_left = minLeft
}
setLeft(_left)
setWidth(_width)
}
document.onmouseup = () => {
document.onmousemove = null
document.onmouseup = null
// 吸附
const newLeft = Math.floor(_left / hourWidth) * hourWidth
setLeft(newLeft)
setWidth(maxWidth - newLeft)
}
}

// 右拉伸
const handleRightMouseDown = (e: any) => {
const startX = e.clientX
let _width = width
document.onmousemove = (e2: any) => {
const endX = e2.clientX
const diffX = endX - startX
_width = width + diffX
// 左限
if(_width <= hourWidth) {
_width = hourWidth
}
// 右限
if(_width >= (measure.rightWidth - left)) {
_width = measure.rightWidth - left
}
setWidth(_width)
}
document.onmouseup = () => {
document.onmousemove = null
document.onmouseup = null
// 吸附
const newWidth = Math.ceil((left + _width) / hourWidth) * hourWidth - left
setWidth(newWidth)
}
}

// 时间范围
const curHours = Math.floor(width * measure.minuteOfWidth / 60)
let leftTime: any = Math.floor(left * measure.minuteOfWidth / 60)
let rightTime = leftTime + curHours
if(rightTime < 10) {
rightTime = '0' + rightTime
}
if(leftTime < 10) {
leftTime = '0' + leftTime
}

return (
<Dropdown trigger={['contextMenu']} overlay={contextMenu} overlayStyle={{width: 80}} placement="bottomRight">
<div className="areabar areabarSelected" style={{left, width}}>
<div className="handlebarLeft" onMouseDown={handleLeftMouseDown}></div>
<div className="area" onMouseDown={handleMouseDown}>
{width > twoHoursWidth && <div className="leftTime">{leftTime}:00</div>}
<div className="centerTime">{curHours}H</div>
{width > twoHoursWidth && <div className="rightTime">{rightTime}:00</div>}
</div>
<div className="handlebarRight" onMouseDown={handleRightMouseDown}></div>
</div>
</Dropdown>
)
}

export default AreaBar