mousedown,mousemove,mouseup实现拖拽
在日常打码中,有可能会遇到通过用户鼠标来移动目标物体,就像上图所示。 在查阅相关博客后。我的思路是通过鼠标按下的位置和移动位置的差值,得到物体应该移动的距离。
let lastPositionX,lastPositionY,nowPostionX,nowPostionY
dragElement.onmousedown=function(){
lastPositionX = event.clentX ;
lastPositionY = event.clentY ;
}
dragElement.onmousemove=function(){
nowPositionX = event.clentX ;
nowPositionY = event.clentY ;
// 物体应该移动的横向距离
let moveeX = nowPostionX - lastPostionX
// 物体应该移动的纵向距离
let moveY = nowPostionY - lastPostionY
/*
得到物体应该移动的距离后我们应该设置物体的位置
*/
}
由于鼠标在物体内,但设置物体距离是设置物体的边到窗口边缘的距离。我们知道鼠标在物体内的相对位置应该是一直保持不变的,因为onmousedown时确定相对距离,所以求出上图中的x,y后每次鼠标移动时可以通过相对位置确定物体的位置。
//onmousedown时确定相对距离
x = event.clientX - drag.offsetLeft;
y = event.clientY - drag.offsetTop;
通过这个方法,我们就不关心物体应该移动的位置,而是关心物体相对于鼠标的位置。那么物体应该设置物体
drag.style.left = event.clientX - x
//把 x = event.clientX - drag.offsetLeft代入上式得:
drag.style.left = drag.offsetLeft + event.clientX(now) - event.clientX(last)
这不就是我们想要的吗?通过相对位置 event.clientX(now) - event.clientX(last)
得到drag元素的位置。
还有一些要注意的事情是,如果鼠标移动的速度过快,有可能跑出元素造成中断移动,所以不能在drag上面注册onmousemove和onmouseup,应该在整个html上。另外注册过的事件可以在结束后清除节省内存。
附上html完整代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body style="background-color: gray;">
<div draggable="true" id="drag" style="background-color: pink; width: 200px;height: 200px;position: absolute;"></div>
</body>
<script type="text/javascript">
var drag = document.getElementById('drag');
drag.onmousedown = function(event) {
var event = event || window.event; //兼容IE浏览器
var x = event.clientX - drag.offsetLeft;
var y = event.clientY - drag.offsetTop;
if (typeof drag.setCapture !== 'undefined') {
drag.setCapture();
}
document.onmousemove = function(event) {
event.preventDefault()
var event = event || window.event;
var moveX = event.clientX - x;
var moveY = event.clientY - y;
if (moveX < 0) {
moveX = 0
} else if (moveX > window.innerWidth - drag.offsetWidth) {
moveX = window.innerWidth - drag.offsetWidth
}
if (moveY < 0) {
moveY = 0
} else if (moveY > window.innerHeight - drag.offsetHeight) {
moveY = window.innerHeight - drag.offsetHeight
}
drag.style.left = moveX + 'px';
drag.style.top = moveY + 'px'
}
document.onmouseup = function(event) {
// 多次点击会注册多次事件造成内存泄漏
document.onmousemove = null;
document.onmouseup = null;
//修复低版本ie bug
if (typeof drag.releaseCapture != 'undefined') {
drag.releaseCapture();
}
}
}
</script>
</html>
在react中,要实现元素的拖拽要拿到dom元素才行,所以我们利用React.CreateRef来创建一个钩子和元素建立联系。
dragElementRef = React.createRef('dragEle');
//操作ref实现拖动效果
const drag = this.dragElementRef.current
//下面的代码和html代码一样
drag.onmousedown = function(event) {
var event = event || window.event; //兼容IE浏览器
var x = event.clientX - drag.offsetLeft;
var y = event.clientY - drag.offsetTop;
if (typeof drag.setCapture !== 'undefined') {
drag.setCapture();
}
document.onmousemove = function(event) {
event.preventDefault()
var event = event || window.event;
var moveX = event.clientX - x;
var moveY = event.clientY - y;
if (moveX < 0) {
moveX = 0
} else if (moveX > window.innerWidth - drag.offsetWidth) {
moveX = window.innerWidth - drag.offsetWidth
}
if (moveY < 0) {
moveY = 0
} else if (moveY > window.innerHeight - drag.offsetHeight) {
moveY = window.innerHeight - drag.offsetHeight
}
drag.style.left = moveX + 'px';
drag.style.top = moveY + 'px'
}
document.onmouseup = function(event) {
// 多次点击会注册多次事件造成内存泄漏
document.onmousemove = null;
document.onmouseup = null;
//修复低版本ie bug
if (typeof drag.releaseCapture != 'undefined') {
drag.releaseCapture();
}
}
}
//render函数返回
<div className={styles.xxx} ref={this.dragElementRef} draggable="true" >
dragstart drag dragend实现拖拽
dragstart drag dragend的方式和mouse的相似,它提供了拖拽和拖放的一些API,拖放是指拖拽后将要放下的位置。 当鼠标点中元素并且开始移动时,就会触发dragstart事件(类比mousedown) 拖拽过程中会持续不断地触发drag事件(类比mousemove) 松开鼠标取消拖拽时就会触发dragend事件(类比mouseup)
当拖拽的元素拖到一个目标元素上时,目标元素会触发以下事件,这里是目标元素的事件
而不是被拖拽元素。
事件名称是 dragenter dragover dragleave drop
拖拽元素到目标上,就会触发dragenter事件(类比mouseover)
如果在mousemove事件中preventDefault()后将监听不到被拖拽元素的drag事件,因为阻止了拖拽的默认行为。
当拖动元素在目标元素中,就会持续触发dragover事件
离开目标元素,触发dragleave事件(类比mouseout)
若拖放元素到了目标元素中(在目标元素中松开鼠标),就会触发drop事件而不会触发dragleave事件
<div draggable="true" id="drag2" style="background-color: yellow; width: 200px;height: 200px;position: absolute; margin-left: 250px;"></div>
drag.ondragstart = function(event) {
var e = event || window.event
console.log('开始拖拽');
}
drag.ondrag = function() {
console.log('拖拽中');
}
drag.ondragend = function() {
console.log('拖拽结束')
}
const target = document.getElementById("drag2")
target.ondragenter = function() {
console.log('进入目标元素')
}
target.ondragover = function(event) {
var event = event || window.event;
console.log('在目标元素中拖拽');
event.preventDefault()
}
target.ondragleave = function() {
console.log('拖放离开目标元素')
}
target.ondrop = function(event) {
console.log('拖放');
var e = event || window.event;
}
拖拽过程中元素的交互,当拖拽元素碰到另一个元素时,可以通过event.dataTransfer这一个中间变量存诗句和取数据,就像localstorage那样。localstorage和datatransfer的区别是localstorage存在于磁盘中而dataTransfer存在于内存,后者的速度更快
e.dataTransfer.setData('text',e.target.id);
类似于localstorage.setItem('text',e.target.id)
e.dataTransfer.getData('text',e.target.id);
类似于localstorage.getItem('text',e.target.id)
下面这个例子实现把一个元素放入另一个元素里面,通过dataTransfer,比起原先的代码值增加了两行。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body style="background-color: gray;">
<div draggable="true" id="drag" style="background-color: pink; width: 200px;height: 200px;position: absolute;"></div>
<div draggable="true" id="drag2" style="background-color: yellow; width: 200px;height: 200px;position: absolute; margin-left: 250px;"></div>
</body>
<script type="text/javascript">
var drag = document.getElementById('drag');
drag.ondragstart = function(event) {
var e = event || window.event
console.log('开始拖拽');
e.dataTransfer.setData('text',e.target.id); //增加
}
drag.ondrag = function() {
console.log('拖拽中');
}
drag.ondragend = function() {
console.log('拖拽结束')
}
const target = document.getElementById("drag2")
target.ondragenter = function() {
console.log('进入目标元素')
}
target.ondragover = function(event) {
var event = event || window.event;
console.log('在目标元素中拖拽');
event.preventDefault()
}
target.ondragleave = function() {
console.log('拖放离开目标元素')
}
target.ondrop = function(event) {
console.log('拖放');
var e = event || window.event;
var data = e.dataTransfer.getData('text');
e.target.appendChild(document.getElementById(data));//增加
}
</script>
</html>
在 dataTransfer还有一些重要的api,用于规定拖拽元素的行为。
dropEffect
dropEffect属性值为字符串,表示被拖动元素可以执行哪一种放置行为
要使用这个属性,必须在dragenter事件处理函数中设置
none
不能把元素拖放至此(除文本框外全部元素的默认值)
move
移动到目标
copy
复制到目标
link
目标打开拖动元素(拖动元素必须是链接并有URL)
effectAllowed
effectAllowed属性值也是字符串,表示允许拖动元素哪种dropEffect
要使用这个属性,必须在dragst事件处理函数中设置
uninitialized
没有设置任何拖放行为
none
不能由任何行为
copy
仅允许dropEffect值为copy
link
仅允许dropEffect值为link
move
仅允许dropEffect值为move
copyLink
允许dropEffect值为copy和link
copyMove
允许dropEffect值为copy和move
linkMove
允许dropEffect值为link和move
all
允许任意dropEffect
参考链接:https://blog.csdn.net/weixin_41910848/article/details/82218243
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!