把拖动div功能用react封装成class,在页面直接引入该class即可使用。

title为可拖动区域。panel为要实现拖动的容器。

优化了拖动框超出页面范围的情况,也优化了拖动太快时鼠标超出可拖动区域的情况,优化了拖动会卡顿的情况。

页面中添加引入方法:

<Draggable panelId="要拖动容器的id" titleId="容器内标题的id" contentId="容器内除标题外的其他部分id" setPanelPosition={this.setPanelPosition.bind(this)}/>

页面中添加拖拽回调函数

  //推拽回调函数
setPanelPosition(left,top){
this.setState({pageX: left, pageY: top})
}

要拖动的div如下:

<div id="要拖动的id" style={{left:this.state.pageX,top:this.state.pageY}}></div>

封装的class代码:

import React from 'react';
class Draggable extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
//拖拽
initDrag(){
let {panelId,titleId,contentId} = this.props;
this.panelDom = document.getElementById(panelId);
this.titleDom = document.getElementById(titleId);
this.contentDom = document.getElementById(contentId);
this.backgroundDom = document.body;
this.bindEvent();
} //region event
componentDidMount() {
this.initDrag();
}
bindEvent(){
this.titleDom.onmousedown = this.onMouseDown.bind(this);
this.titleDom.onmouseup = this.onMouseUp.bind(this);
this.titleDom.onmousemove = this.onMouseMove.bind(this); this.contentDom.onmouseup = this.onContentMouseUp.bind(this);
this.contentDom.onmousemove = this.onContentMouseMove.bind(this); this.backgroundDom.onmouseup = this.onBackgroundMouseUp.bind(this);
this.backgroundDom.onmousemove = this.onBackgroundMouseMove.bind(this);
let step = ()=>{
this.activeAnimation = true;
window.requestAnimationFrame(step);
};
window.requestAnimationFrame(step);
} /**
* 鼠标按下,设置modal状态为可移动,并注册鼠标移动事件
* 计算鼠标按下时,指针所在位置与modal位置以及两者的差值
**/
onMouseDown (e) {
const position = this.getPosition(e)
this.setState({moving: true, diffX: position.diffX, diffY: position.diffY})
} // 松开鼠标,设置modal状态为不可移动
onMouseUp (e) {
const { moving } = this.state
moving && this.setState({moving: false});
} // 鼠标移动重新设置modal的位置
onMouseMove (e) {
const {moving, diffX, diffY} = this.state
if (moving) {
if(this.activeAnimation){
// 获取鼠标位置数据
const position = this.getPosition(e)
// 计算modal应该随鼠标移动到的坐标
const x = position.mouseX - diffX
const y = position.mouseY - diffY
// 窗口大小,结构限制,需要做调整,减去侧边栏宽度
const { clientWidth, clientHeight } = document.documentElement
const modal = this.panelDom
if (modal) {
// 计算modal坐标的最大值
const maxHeight = clientHeight - modal.offsetHeight
const maxWidth = clientWidth - modal.offsetWidth
// 判断得出modal的最终位置,不得超出浏览器可见窗口
const left = x > 0 ? (x < maxWidth ? x : maxWidth) : 0
const top = y > 0 ? (y < maxHeight ? y : maxHeight) : 0
if(this.props.setPanelPosition){
this.props.setPanelPosition(left,top);
}
}
this.activeAnimation = false;
}
}
}
onContentMouseMove(e){
let obj = {};
obj.target = this.titleDom;
obj.pageX = e.pageX;
obj.screenY = e.screenY;
this.onMouseMove(obj);
}
onContentMouseUp(){
this.onMouseUp();
}
onBackgroundMouseMove(e){
let obj = {};
obj.target = this.titleDom;
obj.pageX = e.pageX;
obj.screenY = e.screenY;
this.onMouseMove(obj);
}
onBackgroundMouseUp(){
this.onMouseUp();
}
//endregion //region request
// 获取鼠标点击title时的坐标、title的坐标以及两者的位移
getPosition (e) {
// 标题DOM元素titleDom
const titleDom = e.target
// titleDom的坐标(视窗)
const X = titleDom.getBoundingClientRect().left
// 由于Y轴出现滚动条,需要与鼠标保持一致,存储页面相对位置
const Y = this.panelDom.offsetTop // 鼠标点击的坐标(页面)
let mouseX = e.pageX
let mouseY = e.screenY
// 鼠标点击位置与modal的位移
const diffX = mouseX - X
const diffY = mouseY - Y
return {X, Y, mouseX, mouseY, diffX, diffY}
}
//endregion //region render
//endregion //region clear
//endregion render() {
return (
<>
</>
);
}
}
export default Draggable;

react中实现可拖动div的更多相关文章

  1. 理解React中es6方法创建组件的this

    首发于:https://mingjiezhang.github.io/(转载请说明此出处). 在JavaScript中,this对象是运行时基于函数的执行环境(也就是上下文)绑定的. 从react中的 ...

  2. React中props.children和React.Children的区别

    在React中,当涉及组件嵌套,在父组件中使用props.children把所有子组件显示出来.如下: function ParentComponent(props){ return ( <di ...

  3. react中createFactory, createClass, createElement分别在什么场景下使用,为什么要这么定义?

    作者:元彦链接:https://www.zhihu.com/question/27602269/answer/40168594来源:知乎著作权归作者所有,转载请联系作者获得授权. 三者用途稍有不同,按 ...

  4. React中父组件与子组件之间的数据传递和标准化的思考

    React中父组件与子组件之间的数据传递的的实现大家都可以轻易做到,但对比很多人的实现方法,总是会有或多或少的差异.在一个团队中,这种实现的差异体现了每个人各自的理解的不同,但是反过来思考,一个团队用 ...

  5. React中使用CSSTransitionGroup插件实现轮播图

    动画效果,是一个页面上必不可少的功能,学习一个新的东西,当然就要学习,如何用新的东西,用它的方法去实现以前的东西啦.今天呢,我就在这里介绍一个试用react-addons-css-transition ...

  6. React中的路由系统

    React中的路由系统 提起路由,首先想到的就是 ASPNET MVC 里面的路由系统--通过事先定义一组路由规则,程序运行时就能自动根据我们输入的URL来返回相对应的页面.前端中的路由与之类似,前端 ...

  7. 关于React中状态保存的研究

    在使用react搭配react-router做应用的时候,你可能遇到这样的问题,当我从第一个页面过渡到第二个页面,然后返回之后,发现之前的页面的状态全部不见了,即回到了初始的状态. 这点在页面存在多个 ...

  8. React 深入系列1:React 中的元素、组件、实例和节点

    文:徐超,<React进阶之路>作者 授权发布,转载请注明作者及出处 React 深入系列,深入讲解了React中的重点概念.特性和模式等,旨在帮助大家加深对React的理解,以及在项目中 ...

  9. React 中阻止事件冒泡的问题

    在正式开始前,先来看看 JS 中事件的触发与事件处理器的执行. JS 中事件的监听与处理 事件捕获与冒泡 DOM 事件会先后经历 捕获 与 冒泡 两个阶段.捕获即事件沿着 DOM 树由上往下传递,到达 ...

随机推荐

  1. 三角函数与缓入缓出动画及C#实现(图文讲解)

    日常经常能看到缓入缓出的动画效果,如: 1,带缓入缓出效果的滚动条: 2,带缓入缓出效果的呼吸灯: 像上面这种效果,就是用到了三角函数相关的知识,下面将从头开始一步步去讲解如何实现这种效果. 一.基础 ...

  2. class 类组件:

    ES6  中的class 类组件: // class 关键字:确定一个类型student以类的概念存在 class student{ //构造函数 是默认自动执行 // 初始化 name age 属性 ...

  3. 12.DRF-节流

    Django rest framework源码分析(3)----节流 添加节流 自定义节流的方法 限制60s内只能访问3次 (1)API文件夹下面新建throttle.py,代码如下: # utils ...

  4. 三文搞懂学会Docker容器技术(上)

    1,Docker简介 1.1 Docker是什么? Docker官网: https://www.docker.com/ Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2. ...

  5. 5、struct2的支持ModelDriver获得参数

    1.在以前的代码中我们我们需要获得jsp传递过来的参数我们采用下面的方式获得 package com.weiyuan.test; /** * struct2的action可以不继承任何框架的接口 * ...

  6. css3 小三角的用法

    <div class="arrow-up"> <!--向上的三角--> </div> <div class="arrow-dow ...

  7. springboot + rabbitmq 用了消息确认机制,感觉掉坑里了

    本文收录在个人博客:www.chengxy-nds.top,技术资源共享,一起进步 最近部门号召大伙多组织一些技术分享会,说是要活跃公司的技术氛围,但早就看穿一切的我知道,这 T M 就是为了刷KPI ...

  8. Linux CentOS 7 下dotnet core webpai + nginx 部署

    参考:https://www.jianshu.com/p/b1f573ca50c7 跟着做到,配置nginx访问dotnet core网站时,报错了. 错误如下所示—— 查看nginx的错误日志: c ...

  9. YOLO-V3实战(darknet)

    一. 准备工作 1)实验环境: darknet 是由 C 和 CUDA 开发的,不需要配置其他深度学习的框架(如,tensorflow.caffe 等),支持 CPU 和 GPU 运算,而且安装过程非 ...

  10. python数据结构-最全的六种排序

    1.冒泡排序: 比较相邻的元素,如果第一个比第二个大,那就交换位置 让大的元素跟下一个相邻的元素作比较,如果大于交换位置 对所有元素重复以上步骤(除了最后一个),直到没有任何一个需要作对比 2.选择排 ...