一、h5 drag 实现简易拖动
- 被拖动的元素 dragstart开始 -> drag拖动中 -> dragend拖动结束
- 目的地对象 dragenter被拖动元素进入目的对象 -> dragover目的对象内 -> dragleave离开目的元素
- 到达目的地之后,释放元素事件drop 需要取消浏览器的默认行为
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#range {
position: relative;
width: 600px;
height: 400px;
margin: 10px;
background-color: rgb(133, 246, 250);
}
.box1,
.box2 {
height: 100px;
width: 100px;
cursor: move;
margin-top: 30px;
}
.box1 {
color: #fff;
background-color: #504f4d;
}
.box2 {
background-color: #ff9204;
}
</style>
</head>
<body>
<div id="range">
<!-- 为了使元素可拖动,把draggable属性设置为true。
true: 可以拖动 false: 禁止拖动 auto: 跟随浏览器定义是否可以拖动
文本、图片和链接是默认可以拖放的
-->
<div class="box1" draggable="true" id="source">source box1</div>
<div class="box2" draggable="true" id="target">target box2</div>
</div>
<script>
const main = document.getElementById("range");
const icon = document.querySelector(".icon");
const source = document.getElementById("source");
const target = document.getElementById("target");
source.ondragstart = function (event) {
var e = event || window.event;
e.dataTransfer.setData("Text", e.target.id);
// 在元素开始被拖动时候触发
console.log("开始拖拽", e.target.id);
};
source.ondrag = function () {
// 在元素被拖动时反复触发
console.log("拖拽中");
};
source.ondragend = function () {
// 在拖动操作完成时触发
console.log("拖拽结束");
};
// 目标元素
target.ondragenter = function () {
// 当被拖动元素进入目的地元素所占据的屏幕空间时触发
// dragenter和dragover事件的默认行为是拒绝接受任何被拖放的元素
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 ev = event || window.event;
ev.preventDefault();
// 目标dom 放到 拖动dom 之前
// 父节点.insertBefore(新的子节点,作为参考的子节点);
var data = ev.dataTransfer.getData("Text");
const sourceDom = document.getElementById(data);
sourceDom.parentNode.insertBefore(ev.target, sourceDom);
};
target.ondragstart = function (event) {
var e = event || window.event;
e.dataTransfer.setData("Text", e.target.id);
console.log("开始拖拽", e.target.id);
};
// 目标元素
source.ondragenter = function () {
console.log("进入目标元素");
};
source.ondragover = function (event) {
var event = event || window.event;
console.log("在目标元素中拖拽");
event.preventDefault();
};
source.ondragleave = function () {
console.log("拖放离开目标元素");
};
source.ondrop = function (event) {
console.log("进行放置");
var ev = event || window.event;
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
console.log("进行放置:data: ", ev.target, data);
const sourceDom = document.getElementById(data);
sourceDom.parentNode.insertBefore(ev.target, sourceDom);
};
</script>
</body>
</html>
二、mousedown、mousemove和mouseup 实现简易拖动
1、鼠标按下mousedown 记录当前坐标,拖拽状态move=true,得到 移动过程中不变的值deltaLeft = e.clientX - e.target.offsetLeft
2、鼠标移动onmousemove:计算left 和top 移动的距离,移动
3、鼠标抬起onmouseup: move=false
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#range {
position: relative;
width: 600px;
height: 400px;
margin: 10px;
background-color: rgb(133, 246, 250);
}
.icon {
position: absolute;
height: 100px;
width: 100px;
cursor: move;
background-color: #ff9204;
user-select: none;
}
</style>
</head>
<body>
<div id="range">
<div class="icon">100*100</div>
</div>
<script>
const main = document.getElementById("range");
const icon = document.querySelector(".icon");
let move = false;
let deltaLeft = 0,
deltaTop = 0;
// 拖动开始事件,要绑定在被移动元素上
icon.addEventListener("mousedown", function (e) {
/*
* @des deltaLeft 即移动过程中不变的值
* clientX:鼠标指针距离可视窗口左侧边缘的距离,
* 随滚动条变化而变化,如果拖动滚动条让元素距离可视窗口左侧越近,值越小。
* offsetLeft:元素相对其定位父级(offsetParent)的左偏移量。
*/
deltaLeft = e.clientX - e.target.offsetLeft;
deltaTop = e.clientY - e.target.offsetTop;
move = true;
});
// 移动触发事件要放在,区域控制元素上
main.addEventListener("mousemove", function (e) {
if (move) {
const cx = e.clientX;
const cy = e.clientY;
/** 相减即可得到相对于父元素移动的位置 */
let dx = cx - deltaLeft;
let dy = cy - deltaTop;
/** 防止超出父元素范围 */
if (dx < 0) dx = 0;
if (dy < 0) dy = 0;
if (dx > 500) dx = 500;
if (dy > 300) dy = 300;
icon.setAttribute("style", `left:${dx}px;top:${dy}px`);
}
});
// 拖动结束触发要放在,区域控制元素上
main.addEventListener("mouseup", function (e) {
move = false;
console.log("mouseup");
});
</script>
</body>
</html>