react中实现可拖动div
把拖动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的更多相关文章
- 理解React中es6方法创建组件的this
首发于:https://mingjiezhang.github.io/(转载请说明此出处). 在JavaScript中,this对象是运行时基于函数的执行环境(也就是上下文)绑定的. 从react中的 ...
- React中props.children和React.Children的区别
在React中,当涉及组件嵌套,在父组件中使用props.children把所有子组件显示出来.如下: function ParentComponent(props){ return ( <di ...
- react中createFactory, createClass, createElement分别在什么场景下使用,为什么要这么定义?
作者:元彦链接:https://www.zhihu.com/question/27602269/answer/40168594来源:知乎著作权归作者所有,转载请联系作者获得授权. 三者用途稍有不同,按 ...
- React中父组件与子组件之间的数据传递和标准化的思考
React中父组件与子组件之间的数据传递的的实现大家都可以轻易做到,但对比很多人的实现方法,总是会有或多或少的差异.在一个团队中,这种实现的差异体现了每个人各自的理解的不同,但是反过来思考,一个团队用 ...
- React中使用CSSTransitionGroup插件实现轮播图
动画效果,是一个页面上必不可少的功能,学习一个新的东西,当然就要学习,如何用新的东西,用它的方法去实现以前的东西啦.今天呢,我就在这里介绍一个试用react-addons-css-transition ...
- React中的路由系统
React中的路由系统 提起路由,首先想到的就是 ASPNET MVC 里面的路由系统--通过事先定义一组路由规则,程序运行时就能自动根据我们输入的URL来返回相对应的页面.前端中的路由与之类似,前端 ...
- 关于React中状态保存的研究
在使用react搭配react-router做应用的时候,你可能遇到这样的问题,当我从第一个页面过渡到第二个页面,然后返回之后,发现之前的页面的状态全部不见了,即回到了初始的状态. 这点在页面存在多个 ...
- React 深入系列1:React 中的元素、组件、实例和节点
文:徐超,<React进阶之路>作者 授权发布,转载请注明作者及出处 React 深入系列,深入讲解了React中的重点概念.特性和模式等,旨在帮助大家加深对React的理解,以及在项目中 ...
- React 中阻止事件冒泡的问题
在正式开始前,先来看看 JS 中事件的触发与事件处理器的执行. JS 中事件的监听与处理 事件捕获与冒泡 DOM 事件会先后经历 捕获 与 冒泡 两个阶段.捕获即事件沿着 DOM 树由上往下传递,到达 ...
随机推荐
- redis过期键的策略
一.过期时间设置: 127.0.0.1:6379> expire key seconds //设置键的过期时间为多少秒 127.0.0.1:6379> setex key seconds ...
- SourceTree使用详解(连接远程仓库,克隆,拉取,提交,推送,新建/切换/合并分支,冲突解决)
前言: 俗话说的好工欲善其事必先利其器,Git分布式版本控制系统是我们日常开发中不可或缺的.目前市面上比较流行的Git可视化管理工具有SourceTree.Github Desktop.Tortois ...
- 7000 字说清楚 HashMap,面试点都在里面了
我是风筝,公众号「古时的风筝」,一个兼具深度与广度的程序员鼓励师,一个本打算写诗却写起了代码的田园码农! 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在 ...
- Jmeter系列(32)- 详解 CSV 数据文件设置
如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 了解一哈什么是 CSV 文件 为了实现 ...
- vue-elemnt-admin源码学习
vue-elemnt-admin源码学习 vue-element-admin是一个基于vue,element-ui的集成的管理后台.它的安装部分就不说了,按照官网的步骤一步步就可以执行了. https ...
- Python基础语法一
所有内容都在代码上,有相关代码注释 # #代表注释 # 区分大小写.以回车换行结束 # 多行编写可以使用反斜杠 \ # 缩进代表一个代码块 #数值 #int类型可以使用下划线分割 c=123_456_ ...
- 如何通过Elasticsearch Scroll快速取出数据,构造pandas dataframe — Python多进程实现
首先,python 多线程不能充分利用多核CPU的计算资源(只能共用一个CPU),所以得用多进程.笔者从3.7亿数据的索引,取200多万的数据,从取数据到构造pandas dataframe总共大概用 ...
- 洛谷 P1186 【玛丽卡】
这道题题目真的想吐槽一下...是在机房同学的解释下才看懂的.就是让你求在可以删一条边的情况下,并且删后保证可以到达终点时,求删了后的最大的最短路径. 70分暴力思路: 枚举删边,然后跑一下最短路即可, ...
- spark | 手把手教你用spark进行数据预处理
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是spark专题的第七篇文章,我们一起看看spark的数据分析和处理. 过滤去重 在机器学习和数据分析当中,对于数据的了解和熟悉都是最基 ...
- 这样基于Netty重构RPC框架你不可能知道
原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 今天是猿灯塔“365天原创计划”第5天. 今天呢!灯塔君跟大家讲: 基于Netty重构RPC框架 一.CyclicBarrier方法说明 1. ...