react鼠标拖拽位移
Jedi Hongbin 人气:0场景
三种拖拽条件 可纵轴 横轴 和全部方向 如果加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); };
业务代码
/* * @Author: hongbin * @Date: 2022-04-03 13:38:02 * @LastEditors: hongbin * @LastEditTime: 2022-04-03 21:49:42 * @Description:移动坐标轴 */ 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; } } `;
加载全部内容