本练习demo旨在练习ts的使用,同时熟悉drag相关的事件
1.思路分析
mouse拖拽事件,通常有三个非常重要的过程:onMouseDown(鼠标按下) onMouseMove(鼠标拖动) onMouseUp(鼠标松开),通常我们在使用mouse拖拽这一事件的过程中,大概就是在这三个事件中进行相应的处理 我们最终要实现的demo效果,就是在鼠标按下后能够带动方块随鼠标位置移动,松开后固定在最后的位置。 如图: 移动后: 而这,只需要控制相关的定位:left和top就能实现这个功能(注意,left和top使用前,其position必须被规定为非static(默认) 在这里我们采用最简单的fixed布局就好(当然其他的也可以)
2.与react结合
我们采用react+ts来编写这个demo 创建命令:
1
| npx create-react-app my-drag-demo --typescript
|
创建后直接改动app.tsx
3.节流函数的编写
节流函数的关键在于设置一个闸门,为了避免全局污染,我们用闭包来返回一个由节流函数包装后的函数 手写节流函数这种操作就不再这里赘述了
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const throttle: (func: Function, interval: number) => Function = ( func: Function, interval: number ) => { let timer: any = null; return (...arg: any) => { if (!timer) { timer = setTimeout(() => { func(...arg); timer = null; }, interval); } }; };
|
4.业务逻辑编写
首先对于鼠标的点击,我们需要使用一个boolean变量来进行判断是否处在点击状态,然后用left变量和top变量来记录当前的位置,所以我们可以这样使用
1 2 3
| const [left, setLeft] = useState(0); const [top, setTop] = useState(0); const [click, setClick] = useState(false);
|
定义好之后就可以进行相关逻辑的编写,其中要对onmousemove的逻辑进行节流函数包裹:
1 2 3 4 5 6 7 8 9
| // 移动的事件触发函数 const drag: (event: Object) => void = (event: any) => { if (click) { setLeft(event.clientX - 200); setTop(event.clientY - 200); } }; // 用节流函数包裹后:节流版本 const throttleDrag = throttle(drag, 10);
|
而其他逻辑和样式设置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <div style={{ position: "fixed", left: left + "px", top: top + "px", backgroundColor: "#000000", width: "400px", height: "400px", }} onMouseDown={(event: any) => { setClick(true); setLeft(event.clientX - 200); setTop(event.clientY - 200); }} onMouseMove={(event) => { throttleDrag(event); }} onMouseUp={() => { setClick(false); }} ></div>
|
大功告成!
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| import React, { useRef, useState, useEffect } from "react"; const debounce: (func: Function) => Function = (func: Function) => { let timer: any = null; return (event: Object) => { if (!timer) { timer = setTimeout(() => { func(event); timer = null; }, 10); } }; }; let click = false; function App() { let dragTest = useRef(null); const [left, setLeft] = useState(0); const [top, setTop] = useState(0); useEffect(() => {}, [left, top]); const drag: (event: Object) => void = (event: any) => { if (click) { setLeft(event.clientX - 200); setTop(event.clientY - 200); } }; const debouceDrag = debounce(drag); return ( <div className="App"> <div style={{ position: "fixed", left: left + "px", top: top + "px", backgroundColor: "#000000", width: "400px", height: "400px", }} ref={dragTest} onMouseDown={(event: any) => { click = true; setLeft(event.clientX - 200); setTop(event.clientY - 200); }} onMouseMove={(event) => { debouceDrag(event); }} onMouseUp={() => { click = false; }} ></div> </div> ); }
export default App;
|