场景 三种拖拽条件 可纵轴 横轴 和全部方向 如果加3个监听重复代码太多 因为状态更改组件会重新渲染 所以写的时候要多注意避免有大量代码的函数多次创建销毁
state
const [position, setPosition] = useState(axisPosition);
jsx
<Container
style={{
top: position.top + "px",
left: position.left + "px",
}}
>
<div>
<span
onMouseDown={handleDown(position, (p) => {
setPosition({ ...p, left: position.left });
})}
></span>
<div onMouseDown={handleDown(position, setPosition)}></div>
<span
onMouseDown={handleDown(position, (p) => {
setPosition({ ...p, top: position.top });
})}
></span>
</div>
</Container>
监听
const handleDown =
(position: IPosition, setState: (position: IPosition) => void) => (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
const startX = e.pageX;
const startY = e.pageY;
const { top, left } = position;
const move = (ev: MouseEvent) => {
const disX = ev.pageX - startX;
const disY = ev.pageY - startY;
setState({ left: left + disX, top: top + disY });
};
const cancel = () => {
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", cancel);
document.removeEventListener("mouseleave", cancel);
};
document.addEventListener("mousemove", move);
document.addEventListener("mouseup", cancel);
document.addEventListener("mouseleave", cancel);
};
业务代码
import { FC, ReactElement, useEffect, useState } from "react";
import styled from "styled-components";
import { useElementContext } from "../../context/ElementContext";
import { flexCenter } from "../../styled";
interface IProps {}
interface IPosition {
top: number;
left: number;
}
const handleDown =
(position: IPosition, setState: (position: IPosition) => void) => (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
const startX = e.pageX;
const startY = e.pageY;
const { top, left } = position;
const move = (ev: MouseEvent) => {
const disX = ev.pageX - startX;
const disY = ev.pageY - startY;
setState({ left: left + disX, top: top + disY });
};
const cancel = () => {
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", cancel);
document.removeEventListener("mouseleave", cancel);
};
document.addEventListener("mousemove", move);
document.addEventListener("mouseup", cancel);
document.addEventListener("mouseleave", cancel);
};
const Axis: FC<IProps> = (): ReactElement => {
const { axisPosition } = useElementContext();
const [position, setPosition] = useState<IPosition>(axisPosition);
useEffect(() => {
setPosition(axisPosition);
}, [axisPosition]);
return (
<Container
style={{
top: position.top + "px",
left: position.left + "px",
}}
>
<div>
<span
onMouseDown={handleDown(position, (p) => {
setPosition({ ...p, left: position.left });
})}
></span>
<div onMouseDown={handleDown(position, setPosition)}></div>
<span
onMouseDown={handleDown(position, (p) => {
setPosition({ ...p, top: position.top });
})}
></span>
</div>
</Container>
);
};
export default Axis;
const Container = styled.div`
position: absolute;
z-index: 99999;
transform: translateX(-6px);
& > div {
background: #c711ff;
width: 0px;
height: 0px;
border-radius: 0px;
border: 3px solid #c711ff;
position: relative;
${flexCenter};
span {
position: absolute;
:first-child {
cursor: ns-resize;
background-color: red;
width: 2px;
height: 3vw;
transform: translateY(-60%);
::before {
content: "";
border: 4px solid red;
top: 0;
left: -3px;
position: absolute;
transform: scaleY(4) rotate(180deg);
border-left-color: transparent;
border-bottom-color: transparent;
border-right-color: transparent;
transform-origin: top;
}
}
:last-child {
cursor: ew-resize;
width: 3vw;
height: 2px;
background-color: blue;
transform: translateX(60%);
::before {
content: "";
border: 4px solid blue;
top: -3px;
right: 0;
position: absolute;
transform: scaleX(4) rotate(-90deg) translateY(50%);
border-left-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
}
}
}
div {
cursor: move;
width: inherit;
height: inherit;
border: inherit;
border-radius: inherit;
background-color: inherit;
position: absolute;
z-index: 1;
}
}
`;
|