- 原生js实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>手动实现拖拽</title>
</head>
<style>
.move {
position: absolute;
width: 100px;
height: 100px;
background: gray
}
</style>
<body>
<div class="move-container">
<div class="move">
</div>
</div>
<script>
let elem = document.querySelector('.move');
let dragging; //拖拽状态
let trans, portrait; //鼠标按下时相对于选中元素的位移
document.addEventListener('mousedown', function (e) {
if (e.target == elem) {
dragging = true; //激活拖拽状态
let elemRect = elem.getBoundingClientRect(); //返回元素的大小及其相对于视口的位置
trans = e.clientX - elemRect.left; //鼠标按下时和选中元素的坐标偏移:x坐标
portrait = e.clientY - elemRect.top; //鼠标按下时和选中元素的坐标偏移:y坐标
}
});
document.addEventListener('mouseup', function (e) {
dragging = false;
});
document.addEventListener('mousemove', function (e) {
if (dragging) {
var moveX = e.clientX - trans,
moveY = e.clientY - portrait;
elem.style.left = moveX + 'px';
elem.style.top = moveY + 'px';
}
});
</script>
</body>
</html>
- HTML5原生实现:拖拽draggable属性、DataTranfers对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>手动实现拖拽</title>
</head>
<style>
.main {
display: flex;
justify-content: space-around;
}
.left {
margin-right: 10px;
padding: 1px;
width: 300px;
height: 500px;
text-align: center;
box-sizing: border-box;
border: 1px solid red;
}
.right {
padding: 1px;
width: 300px;
height: 500px;
text-align: center;
box-sizing: border-box;
border: 1px solid lightseagreen;
}
.txt {
margin: 1px;
padding: 5px;
border: 1px solid gray;
cursor: move;
}
</style>
<body>
<main class="main">
<div class="left" id="left">
<div class="txt-show">左边区域</div>
<div id='txt1' draggable="true" class="dragable txt txt1">可移动的文字一</div>
<div id='txt2' draggable="true" class="dragable txt txt2">可移动的文字二</div>
<div id='txt3' draggable="true" class="dragable txt txt3">可移动的文字三</div>
<div id='txt4' draggable="true" class="dragable txt txt4">可移动的文字四</div>
<div id='txt5' draggable="true" class="dragable txt txt5">可移动的文字五</div>
</div>
<div class="right" id='right'>
<div class="txt-show">右边区域</div>
</div>
</main>
<script>
/*
* 注意: 为了让元素可拖动,需要使用 HTML5 draggable 属性。
* 提示: 链接和图片默认是可拖动的,不需要 draggable 属性。
*
* 在拖放的过程中会触发以下事件:
*
* 在拖动目标上触发事件 (源元素):
* ondragstart - 用户开始拖动元素时触发
* ondrag - 元素正在拖动时触发
* ondragend - 用户完成元素拖动后触发
*
* 释放目标时触发的事件:
* ondragenter - 当被鼠标拖动的对象进入其容器范围内时触发此事件
* ondragover - 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
* ondragleave - 当被鼠标拖动的对象离开其容器范围内时触发此事件
* ondrop - 在一个拖动过程中,释放鼠标键时触发此事件
*/
let txtList = document.getElementsByClassName('txt')
for (let i = 0; i < txtList.length; i++) {
txtList[i].ondragstart = handle_start
txtList[i].ondrag = handle_drag
txtList[i].ondragend = handle_end
}
function handle_start(e) {
/*
* dataTransfer.setData() 方法设置被拖数据的数据类型和值
* Text 是一个 DOMString,表示要添加到 drag object 的拖动数据的类型。值是可拖动元素的 id ("drag1")
*/
e.dataTransfer.setData('Text', e.target.id)
console.log(e.target.id, 'handle_start-拖动开始')
}
function handle_drag(e) {
console.log(e.target.id, 'handle_drag-拖动中')
}
function handle_end(e) {
console.log(e.target.id, 'handle_end-拖动结束')
}
let target = document.getElementById('right')
target.ondragenter = handle_enter
target.ondragover = handle_over
target.ondragleave = handle_leave
target.ondrop = handle_drop
function handle_enter(e) {
e.preventDefault()
console.log(e.target.id, 'handle_enter-进入目的地')
}
function handle_over(e) {
/*
* ondragover 事件规定在何处放置被拖动的数据。
* 默认地,无法将数据/元素放置到其他元素中。
* 如果需要设置允许放置,我们必须阻止对元素的默认处理方式:event.preventDefault()。
*
*/
e.preventDefault()
let returnObj = e.dataTransfer.getData('Text')
console.log(returnObj + '-handle_over-在目的地范围内')
}
function handle_leave(e) {
e.preventDefault()
let returnObj = e.dataTransfer.getData('Text')
console.log(returnObj + 'handle_leave-没有放下就离开目的地')
}
function handle_drop(e) {
/*
* 调用 preventDefault() 来避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开)
* 通过 dataTransfer.getData("Text") 方法获得被拖的数据
* 该方法将返回在 setData() 方法中设置为相同类型的任何数据
* 把被拖元素追加到放置元素(目标元素)中
*/
e.stopPropagation() // 不再派发事件。解决Firefox浏览器,打开新窗口的问题。
e.preventDefault()
let returnObj = e.dataTransfer.getData('Text')
if (returnObj) {
e.target.appendChild(document.getElementById(returnObj))
}
console.log(returnObj + '-handle_drop-在目的地区释放')
}
</script>
</body>
</html>
网友评论