一、概述
在日常开发中我们都会遇见一些拖拽DOM元素的需求,本文总结了如何实现DOM元素拖拽功能的方法;主要分为两种;
- 一是通过监听鼠标mouse事件
- 二是使用Html5的拖拽的API drag & drop
二、使用原生js实现拖拽功能
使用该方法时,被拖拽的元素必须为绝对定位;
主要监听鼠标的三个事件:mousedown, onmousemove, onmouseup
// html结构
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
.box {
position: absolute;
background: blue;
}
</style>
</head>
<body>
<div class="box" style="left:0;top:0;width:100px;height:100px">
</div>
</body>
</html>
// js方法
<script>
let dragDiv = document.getElementsByClassName("box")[0];
// 鼠标按下事件 处理程序
let putDown = function (event) {
dragDiv.style.cursor = "pointer";
let offsetX = parseInt(dragDiv.style.left); // 获取当前的x轴距离
let offsetY = parseInt(dragDiv.style.top); // 获取当前的y轴距离
let innerX = event.clientX - offsetX; // 获取鼠标在方块内的x轴距
let innerY = event.clientY - offsetY; // 获取鼠标在方块内的y轴距
// 按住鼠标时为div添加一个border
dragDiv.style.borderStyle = "solid";
dragDiv.style.borderColor = "red";
dragDiv.style.borderWidth = "3px";
// 鼠标移动的时候不停的修改div的left和top值
document.onmousemove = function (event) {
dragDiv.style.left = event.clientX - innerX + "px";
dragDiv.style.top = event.clientY - innerY + "px";
// 边界判断
if (parseInt(dragDiv.style.left) <= 0) {
dragDiv.style.left = "0px";
}
if (parseInt(dragDiv.style.top) <= 0) {
dragDiv.style.top = "0px";
}
if (parseInt(dragDiv.style.left) >= window.innerWidth - parseInt(dragDiv.style.width)) {
dragDiv.style.left = window.innerWidth - parseInt(dragDiv.style.width) + "px";
}
if (parseInt(dragDiv.style.top) >= window.innerHeight - parseInt(dragDiv.style.height)) {
dragDiv.style.top = window.innerHeight - parseInt(dragDiv.style.height) + "px";
}
}
// 鼠标抬起时,清除绑定在文档上的mousemove和mouseup事件
// 否则鼠标抬起后还可以继续拖拽方块
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
// 清除border
dragDiv.style.borderStyle = "";
dragDiv.style.borderColor = "";
dragDiv.style.borderWidth = "";
}
}
// 绑定鼠标按下事件
dragDiv.addEventListener("mousedown", putDown, false);
</script>
// 参考代码,封装拖拽函数
var funDrag = function(element, callback) {
callback = callback || function() {};
var params = {
left: 0,
top: 0,
currentX: 0,
currentY: 0,
flag: false
};
//获取相关CSS属性
var getCss = function(o,key){
return o.currentStyle? o.currentStyle[key] : document.defaultView.getComputedStyle(o,false)[key];
};
//拖拽的实现
if(getCss(element, "left") !== "auto"){
params.left = getCss(element, "left");
}
if(getCss(element, "top") !== "auto"){
params.top = getCss(element, "top");
}
//o是移动对象
element.onmousedown = function(event){
params.flag = true;
event = event || window.event;
params.currentX = event.clientX;
params.currentY = event.clientY;
};
document.onmouseup = function(){
params.flag = false;
if(getCss(element, "left") !== "auto"){
params.left = getCss(element, "left");
}
if(getCss(element, "top") !== "auto"){
params.top = getCss(element, "top");
}
callback();
};
document.onmousemove = function(event){
event = event || window.event;
if(params.flag){
var nowX = event.clientX, nowY = event.clientY;
var disX = nowX - params.currentX, disY = nowY - params.currentY;
element.style.left = parseInt(params.left) + disX + "px";
element.style.top = parseInt(params.top) + disY + "px";
}
}
};
三、使用Html5的特性实现
HTML 的 drag & drop 使用了 DOM event model 以及从mouse events 继承而来的 drag events 。一个典型的drag操作是这样开始的:用户用鼠标选中一个可拖动的(draggable)元素,移动鼠标到一个可放置的(droppable)元素,然后释放鼠标。 在操作期间,会触发一些事件类型,有一些事件类型可能会被多次触发(比如drag 和 dragover 事件类型)
相关重点:
1.DataTransfer 对象:退拽对象用来传递的媒介,使用一般为Event.dataTransfer。
2.draggable 属性:就是标签元素要设置draggable=true,否则不会有效果,例如:
<div title="拖拽我" draggable="true">列表1</div>
3.ondragstart事件:当拖拽元素开始被拖拽的时候触发的事件,此事件作用在被拖曳元素上
4.ondragenter事件:当拖曳元素进入目标元素的时候触发的事件,此事件作用在目标元素上
5.ondragover事件:拖拽元素在目标元素上移动的时候触发的事件,此事件作用在目标元素上
6.ondrop事件:被拖拽的元素在目标元素上同时鼠标放开触发的事件,此事件作用在目标元素上
7.ondragend 事件:当拖拽完成后触发的事件,此事件作用在被拖曳元素上
8.Event.preventDefault()方法:阻止默认的些事件方法等执行。在ondragover中一定要执行preventDefault(),否则ondrop事件不会被触发。另外,如果是从其他应用软件或是文件中拖东西进来,尤其是图片的时候,默认的动作是显示这个图片或是相关信息,并不是真的执行drop。此时需要用用document的ondragover事件把它直接干掉。
9.Event.effectAllowed 属性:就是拖拽的效果。
// html结构
<div class="dustbin"><br />垃<br />圾<br />箱</div>
<div class="dragbox">
<div class="draglist" title="拖拽我" draggable="true">列表1</div>
<div class="draglist" title="拖拽我" draggable="true">列表2</div>
<div class="draglist" title="拖拽我" draggable="true">列表3</div>
<div class="draglist" title="拖拽我" draggable="true">列表4</div>
<div class="draglist" title="拖拽我" draggable="true">列表5</div>
<div class="draglist" title="拖拽我" draggable="true">列表6</div>
</div>
<div class="dragremind"></div>
// js代码
var eleDustbin = $(".dustbin")[0], eleDrags = $(".draglist"), lDrags = eleDrags.length, eleRemind = $(".dragremind")[0], eleDrag = null;
for (var i=0; i<lDrags; i+=1) {
eleDrags[i].onselectstart = function() {
return false;
};
eleDrags[i].ondragstart = function(ev) {
/*拖拽开始*/
//拖拽效果
ev.dataTransfer.effectAllowed = "move";
ev.dataTransfer.setData("text", ev.target.innerHTML);
ev.dataTransfer.setDragImage(ev.target, 0, 0);
eleDrag = ev.target;
return true;
};
eleDrags[i].ondragend = function(ev) {
/*拖拽结束*/
ev.dataTransfer.clearData("text");
eleDrag = null;
return false
};
}
eleDustbin.ondragover = function(ev) {
/*拖拽元素在目标元素头上移动的时候*/
ev.preventDefault();
return true;
};
eleDustbin.ondragenter = function(ev) {
/*拖拽元素进入目标元素头上的时候*/
this.style.color = "#ffffff";
return true;
};
eleDustbin.ondrop = function(ev) {
/*拖拽元素进入目标元素头上,同时鼠标松开的时候*/
if (eleDrag) {
eleRemind.innerHTML = '<strong>"' + eleDrag.innerHTML + '"</strong>被扔进了垃圾箱';
eleDrag.parentNode.removeChild(eleDrag);
}
this.style.color = "#000000";
return false;
};