【练习小demo】使用React+TS实现一个拖动换位置效果(同时应用节流)

本练习demo旨在练习ts的使用,同时熟悉drag相关的事件

1.思路分析

mouse拖拽事件,通常有三个非常重要的过程:onMouseDown(鼠标按下) onMouseMove(鼠标拖动) onMouseUp(鼠标松开),通常我们在使用mouse拖拽这一事件的过程中,大概就是在这三个事件中进行相应的处理
我们最终要实现的demo效果,就是在鼠标按下后能够带动方块随鼠标位置移动,松开后固定在最后的位置。
如图:


移动后:

而这,只需要控制相关的定位:left和top就能实现这个功能(注意,left和top使用前,其position必须被规定为非static(默认)
在这里我们采用最简单的fixed布局就好(当然其他的也可以)

2.与react结合

我们采用react+ts来编写这个demo
创建命令:

npx create-react-app my-drag-demo --typescript

创建后直接改动app.tsx

3.节流函数的编写

节流函数的关键在于设置一个闸门,为了避免全局污染,我们用闭包来返回一个由节流函数包装后的函数
手写节流函数这种操作就不再这里赘述了

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变量来记录当前的位置,所以我们可以这样使用

const [left, setLeft] = useState(0);
const [top, setTop] = useState(0);
const [click, setClick] = useState(false);

定义好之后就可以进行相关逻辑的编写,其中要对onmousemove的逻辑进行节流函数包裹:

// 移动的事件触发函数
  const drag: (event: Object) => void = (event: any) => {
    if (click) {
      setLeft(event.clientX - 200);
      setTop(event.clientY - 200);
    }
  };
  // 用节流函数包裹后:节流版本
  const throttleDrag = throttle(drag, 10);

而其他逻辑和样式设置如下:

 <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>

大功告成!

完整代码:

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;
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇