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 树由上往下传递,到达 ...
随机推荐
- Flutter学习笔记(33)--GestureDetector手势识别
如需转载,请注明出处:Flutter学习笔记(33)--GestureDetector手势识别 这篇随笔主要记录的学习内容是GestureDetector手势识别,内容包括识别单击.双击.长按.组件拖 ...
- 手把手教你学Numpy,搞定数据处理——收官篇
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Numpy专题第6篇文章,我们一起来看看Numpy库当中剩余的部分. 数组的持久化 在我们做机器学习模型的研究或者是学习的时候,在完成 ...
- VM363:1 Uncaught SyntaxError: Invalid or unexpected token
此报错主要是因为json字符串转json对象时,json字符串中出现特殊字符(如:换行符)报错. json字符转json对象(如下写则报错) 更改后 参考地址: https://www.cnblogs ...
- 入门大数据---Flink核心概念综述
一.Flink 简介 Apache Flink 诞生于柏林工业大学的一个研究性项目,原名 StratoSphere .2014 年,由 StratoSphere 项目孵化出 Flink,并于同年捐赠 ...
- offer到手!美团Java岗四面(多线程+redis+JVM+数据库)
美团Java岗四面,已拿offer,前三面都是技术面,第四面是HR面,下面是面试题! 美团Java岗一面(技术,电话面,约40分钟) 自我介绍. 项目介绍. 了解过redis源码及redis集群么? ...
- 谈谈javaSE中的==和equals的联系与区别
前言 ==和equals是我们面试中经常会碰到的问题.那么它们之间有什么联系和区别呢?今天我们就来聊聊吧! 问题 这里先抛出一些比较典型笔试问题: int x = 10; int y = 10; St ...
- STL初步学习(queue,deque)
4.queue queue就是队列,平时用得非常多.栈的操作是只能是先进先出,与栈不同,是先进后出,与之后的deque也有区别.个人感觉手写队列有点麻烦,有什么head和tail什么的,所以说 STL ...
- HTML5(七)Web 存储
HTML5 Web 存储 HTML5 web 存储,一个比cookie更好的本地存储方式. 什么是 HTML5 Web 存储? 使用HTML5可以在本地存储用户的浏览数据. 早些时候,本地存储使用的是 ...
- 【区间DP】低价回文
[区间DP]低价回文 标签(空格分隔): 区间DP 回文词 [题目描述] 追踪每头奶牛的去向是一件棘手的任务,为此农夫约翰安装了一套自动系统.他在每头牛身上安装了一个电子身份标签,当奶牛通过扫描器的时 ...
- 宁波市第三届网络安全大赛-WriteUp(Misc)
友情链接 Web师傅:skyxmao师傅 内心OS 第一次参加这种大型比赛,实力较菜,请师傅们多多指点 Misc | 完成 | 第一 下载文件,看一下doc没有任何问题, 没有发现任何隐写,然后修改文 ...