react优雅处理多条件鼠标拖拽位移

本文实例为大家分享了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;
    }
  }
`;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 使用react-beautiful-dnd实现列表间拖拽踩坑

    为什么选用react-beautiful-dnd 相比于react-dnd,react-beautiful-dnd更适用于列表之间拖拽的场景,支持移动端,且较为容易上手. 基本使用方法 基本概念 DragDropContext:构建一个可以拖拽的范围 onDragStart:拖拽开始回调 onDragUpdate:拖拽中的回调 onDragEnd:拖拽结束时的回调 Droppable - 可以放置拖拽块的区域 Draggalbe - 可被拖拽的元素 使用方法 把你想能够拖放的代码放到DragDr

  • react-dnd实现任意拖动与互换位置

    本文实例为大家分享了react-dnd实现任意拖动与互换位置的具体代码,供大家参考,具体内容如下 react-dnd用法 hooks组件 1.使用DndProvider定义一个可以拖拽的范围 import { HTML5Backend } from 'react-dnd-html5-backend'; import { DndProvider } from 'react-dnd'; class App extends Component{   render () {     return (  

  • react实现自定义拖拽hook

    前沿 最近发现公司的产品好几个模块用到了拖拽功能,之前拖拽组件是通过Html5 drag Api 实现的但体验并不是很好,顺便将原来的拖拽组建稍做修改,写一个自定义hook,方便大家使用拖拽功能. 正文 拖拽功能原理: 1.拖拽元素通过addEventListener监听器添加鼠标按下,鼠标移动,以及鼠标抬起事件.2.再通过getBoundingClientRect() 得到拖拽元素四周相对于可拖拽区域边界的距离.3.鼠标移动时计算x轴和y轴的移动偏移量.4.通过element.style.tr

  • React拖拽调整大小的组件

    本文实例为大家分享了React拖拽调整大小的组件,供大家参考,具体内容如下 一.实现流程 1.使用React.cloneElement加强包裹组件,在包裹的组件设置绝对定位,并在组件内加上四个可调整大小的拖动条,在点击拖动条并进行拖动时会改变DragBox的大小,如下: 2.使用: <DragBox dragAble={true} minWidth={350} minHeight={184} edgeDistance={[10, 10, 10, 10]} dragCallback={this.d

  • react实现拖拽模态框

    前言 实际开发中,模态框展现数据会经常出现.但不幸的是有时功能开发完了,UI同学突然提出需求希望模态框能拖拽.本文使用的模态框由 ant design 3.0 的 Modal 组件封装而成,如何在不修改原来代码的基础上实现拖拽呢.最终效果图如下: 实践 1.创建高阶组件DragHoc 新建文件ModalDrag/index.js,将下面代码copy进去 DragObj是具体拖拽的原生js代码,后面再看 DragHoc是创建高阶组件的函数,其中参数InnerComponent是需要被改造的模态框组

  • react-beautiful-dnd 实现组件拖拽

    一个React.js 的 漂亮,可移植性 列表拖拽库.想了解更多react-beautiful-dnd特点适用人群请看官方文档.中文翻译文档 npm:https://www.npmjs.com/package/react-beautiful-dnd 1.安装 ​ 在已有react项目中 执行以下命令 so easy. # yarn yarn add react-beautiful-dnd # npm npm install react-beautiful-dnd --save 2.APi 详情查

  • react-native 圆弧拖动进度条实现的示例代码

    本文介绍了react-native 圆弧拖动进度条实现的示例代码,分享给大家,具体如下: 先上效果图 因为需求需要实现这个效果图 非原生实现, 难点1:绘制 使用svg 难点2:点击事件的处理 难点3:封装 由于绘制需要是使用svg 此处自行百度 按照svg以及api 教学 视图代码块 render() { return ( <View pointerEvents={'box-only'} //事件处理 {...this._panResponder.panHandlers}> //实际圆环 {

  • react优雅处理多条件鼠标拖拽位移

    本文实例为大家分享了react优雅处理多条件鼠标拖拽位移的具体代码,供大家参考,具体内容如下 场景 三种拖拽条件 可纵轴 横轴 和全部方向 如果加3个监听重复代码太多因为状态更改组件会重新渲染 所以写的时候要多注意避免有大量代码的函数多次创建销毁 state const [position, setPosition] = useState(axisPosition); jsx <Container       style={{         top: position.top + "px

  • 使用纯JS实现checkbox的框选效果(鼠标拖拽多选)

    目录 主要思路 css 代码如下 html结构如下 js主要逻辑如下 总结 主要思路 用一个盒子作为选区,通过定位让其固定在左上角,由于没有给定选区元素的宽高所以默认不显示,在 onmousemove 中动态获取选区定位的top left bottom right四个属性,同时将鼠标拖拽的距离作为选区的宽高,由于给选区元素的css设置了border就呈现出如图所示的框选效果.(注意:要想自己手动勾选复选框,要给选区元素的css设置pointer-events: none;否则点击复选框的事件会被

  • js实现使用鼠标拖拽切换图片的方法

    本文实例讲述了js实现使用鼠标拖拽切换图片的方法.分享给大家供大家参考.具体实现方法如下: <script type="text/javascript" src="js/jquery.min.js"></script> <style type="text/css"> *{margin:0;padding:0;} .m-slider{width:600px;margin:0 auto 10px !importan

  • js实现登录框鼠标拖拽效果

    效果图: 代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录框鼠标拖拽效果</title> <style type="text/css"> body { background: url("https://timgsa.baidu.com/timg?i

  • jsMind通过鼠标拖拽的方式调整节点位置

    jsMind是一个纯javascript实现的思维导图类库,基于html5的canvas实现,以BSD协议开源. 提供了思维导图的显示,编辑等功能,支持freemind数据格式,有丰富的开发接口可供使用,具体功能请访问软件主页进一步了解. jsMind 现已支持通过鼠标拖拽的方式调整节点位置了.只需引用最新版本的 jsmind.js 以及 jsmind.draggable.js 即可使用该功能.需要注意的是,当思维导图设置为不可编辑的时候,拖拽功能也将同时禁止. 请访问 项目主页:http://

  • 使用javaScript实现鼠标拖拽事件

    本文实例为大家分享了js实现鼠标拖拽事件的具体代码,供大家参考,具体内容如下 <html> <head> <meta charset="UTF-8"> <title></title> <style> body{ margin: 0; padding: 0; } div{ position: absolute; top: 200px;/*div的y轴*/ left: 150px;/*div的x轴*/ width: 3

  • js实现百度登录框鼠标拖拽效果

    以百度的登录窗口为例,学习鼠标拖拽效果如何实现,拖拽范围限定以及登录窗口自动居中.学会如何制作弹出窗口特效,了解把元素设置为可拖拽的原理. 知识点: 1.掌握对可拖拽对话框的实现原理 2.了解元素如何触发脚本方法以及如何编写侦听事件 3. 学会设置元素在页面中居中和全屏 注意区别: 1.screenX:鼠标位置相对于用户屏幕水平偏移量,而screenY也就是垂直方向的,此时的参照点也就是原点是屏幕的左上角. 2.clientX:跟screenX相比就是将参照点改成了浏览器内容区域的左上角,该参照

  • js实现鼠标拖拽多选功能示例

    最近做了一个用js实现鼠标拖拽多选的功能,于是整理了一下思路,写了一个小demo: 遮罩出现: 被遮罩盖住的,即为选中的块(背景色为粉色) 下面是具体代码,注释已在文中,与大家交流. <!DOCTYPE html> <html> <head> <title>鼠标拖拽多选功能</title> <script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"&

  • 基于jquery实现的鼠标拖拽元素复制并写入效果

    直接上代码: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-eq

  • jquery实现鼠标拖拽滑动效果来选择数字的方法

    本文实例讲述了jquery实现鼠标拖拽滑动效果来选择数字的方法.分享给大家供大家参考.具体如下: 这是使用jquery ui实现的一个精美实用的效果,可以通过鼠标拖拽滑动效果来选择数字 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns

随机推荐