如何用React实现优雅的多条件鼠标拖拽位移处理?
- 内容介绍
- 文章标签
- 相关推荐
本文共计965个文字,预计阅读时间需要4分钟。
本文分享了React优雅处理多条件鼠标拖拽移动的整体代码示例。供大家参考。
场景:- 实现鼠标拖拽元素在容器内移动的功能。
内容:- 场景描述- 三种拖拽条件- 可滑动方向- 垂直、水平滚动条- 全方位方向支持- 避免三个监听重复代码,因状态更新
具体代码示例:
jsxconst { useState }=React;
const Draggable=({ initialX, initialY, onMove })=> { const [position, setPosition]=useState({ x: initialX, y: initialY });
const handleMouseDown=(e)=> { const { clientX, clientY }=e; const deltaX=clientX - position.x; const deltaY=clientY - position.y;
const onMouseMove=(e)=> { const newX=e.clientX - deltaX; const newY=e.clientY - deltaY;
if (onMove(newX, newY)) { setPosition({ x: newX, y: newY }); } };
const onMouseUp=()=> { window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mouseup', onMouseUp); };
window.addEventListener('mousemove', onMouseMove); window.addEventListener('mouseup', onMouseUp); };
return ( );};
const App=()=> { const handleMove=(x, y)=> { // Check your conditions here and decide whether to allow movement // Example: x > 0 && y > 0 && x return ( );}; 这段代码展示了一个可拖拽的红色方块,拖拽时会根据条件允许或不允许移动。`handleMove` 函数可以根据实际需求来编写具体的拖拽条件。 本文实例为大家分享了react优雅处理多条件鼠标拖拽位移的具体代码,供大家参考,具体内容如下 三种拖拽条件 可纵轴 横轴 和全部方向 如果加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;
}
}
`;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持易盾网络。场景
因为状态更改组件会重新渲染 所以写的时候要多注意避免有大量代码的函数多次创建销毁
本文共计965个文字,预计阅读时间需要4分钟。
本文分享了React优雅处理多条件鼠标拖拽移动的整体代码示例。供大家参考。
场景:- 实现鼠标拖拽元素在容器内移动的功能。
内容:- 场景描述- 三种拖拽条件- 可滑动方向- 垂直、水平滚动条- 全方位方向支持- 避免三个监听重复代码,因状态更新
具体代码示例:
jsxconst { useState }=React;
const Draggable=({ initialX, initialY, onMove })=> { const [position, setPosition]=useState({ x: initialX, y: initialY });
const handleMouseDown=(e)=> { const { clientX, clientY }=e; const deltaX=clientX - position.x; const deltaY=clientY - position.y;
const onMouseMove=(e)=> { const newX=e.clientX - deltaX; const newY=e.clientY - deltaY;
if (onMove(newX, newY)) { setPosition({ x: newX, y: newY }); } };
const onMouseUp=()=> { window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mouseup', onMouseUp); };
window.addEventListener('mousemove', onMouseMove); window.addEventListener('mouseup', onMouseUp); };
return ( );};
const App=()=> { const handleMove=(x, y)=> { // Check your conditions here and decide whether to allow movement // Example: x > 0 && y > 0 && x return ( );}; 这段代码展示了一个可拖拽的红色方块,拖拽时会根据条件允许或不允许移动。`handleMove` 函数可以根据实际需求来编写具体的拖拽条件。 本文实例为大家分享了react优雅处理多条件鼠标拖拽位移的具体代码,供大家参考,具体内容如下 三种拖拽条件 可纵轴 横轴 和全部方向 如果加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;
}
}
`;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持易盾网络。场景
因为状态更改组件会重新渲染 所以写的时候要多注意避免有大量代码的函数多次创建销毁

