基于鼠标事件的拖拽
原理——onmousedown、onmousemove、onmouseup
-
onmousedown-
该事件会在鼠标按键按下时触发
-
支持该事件的HTML标签
<a>, <address>, <area>, <b>, <bdo>, <big>, <blockquote>, <body>, <button>, <caption>, <cite>, <code>, <dd>, <dfn>, <div>, <dl>, <dt>, <em>, <fieldset>, <form>, <h1> to <h6>, <hr>, <i>, <img>, <input>, <kbd>, <label>, <legend>, <li>, <map>, <ol>, <p>, <pre>, <samp>, <select>, <small>, <span>, <strong>, <sub>, <sup>, <table>, <tbody>, <td>, <textarea>, <tfoot>, <th>, <thead>, <tr>, <tt>, <ul>, <var> -
支持该事件的JavaScript对象
button, document, link
-
-
onmousemove-
该事件会在鼠标指针移动时触发
-
支持该事件的HTML标签
<a>, <address>, <area>, <b>, <bdo>, <big>, <blockquote>, <body>, <button>, <caption>, <cite>, <code>, <dd>, <dfn>, <div>, <dl>, <dt>, <em>, <fieldset>, <form>, <h1> to <h6>, <hr>, <i>, <img>, <input>, <kbd>, <label>, <legend>, <li>, <map>, <ol>, <p>, <pre>, <samp>, <select>, <small>, <span>, <strong>, <sub>, <sup>, <table>, <tbody>, <td>, <textarea>, <tfoot>, <th>, <thead>, <tr>, <tt>, <ul>, <var> -
支持该事件的JavaScript对象
默认情况下,onmousemove不是任何对象的事件,因为鼠标移动非常频繁
-
-
onmouseup-
该事件会在鼠标按键松开时触发
-
支持该对象的HTML标签
<a>, <address>, <area>, <b>, <bdo>, <big>, <blockquote>, <body>, <button>, <caption>, <cite>, <code>, <dd>, <dfn>, <div>, <dl>, <dt>, <em>, <fieldset>, <form>, <h1> to <h6>, <hr>, <i>, <img>, <input>, <kbd>, <label>, <legend>, <li>, <map>, <ol>, <p>, <pre>, <samp>, <select>, <small>, <span>, <strong>, <sub>, <sup>, <table>, <tbody>, <td>, <textarea>, <tfoot>, <th>, <thead>, <tr>, <tt>, <ul>, <var> -
支持该事件的JavaScript对象
button, document, link
-
具体实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#test {
width: 100px;
height: 100px;
background: #000;
position: absolute;
color: #fff;
}
</style>
</head>
<body>
<div id="test">4616125</div>
<script>
(function() {
function Code() {}
Code.prototype = {
addEvent: function() {
var that = this;
var oDiv = document.getElementById('test');
oDiv.onmousedown = function(ev) {
var ev = ev || event;
var distanceX = ev.clientX - this.offsetLeft;
var distanceY = ev.clientY - this.offsetTop;
if (oDiv.setCapture) {
oDiv.setCapture();
}
document.onmousemove = function(ev) {
var ev = ev || event;
oDiv.style.left = ev.clientX - distanceX + 'px';
oDiv.style.top = ev.clientY - distanceY + 'px';
};
document.onmouseup = function(ev) {
document.onmousemove = document.onmouseup = null;
if (oDiv.releaseCapture) {
oDiv.releaseCapture();
}
};
};
},
init: function() {
var that = this;
window.onload = that.addEvent;
},
}
new Code().init();
})();
</script>
</body>
</html>
注意事项及存在的问题
- 注意事项
- 被拖动的元素必须是绝对定位(
position:absolute;) onmousedown事件需要在window.onload时加载- 如果被拖动元素上有文字会有自带的文字拖动效果,需要将该元素上的所有拖动事件绑定在该元素上
onmousemove和onmouseup需要在onmousedown里面绑定,在拖拽完成之后需要重新定义事件值为null
- 被拖动的元素必须是绝对定位(
- 存在的问题
- 会被拖拽出边界,需要进行边界判断
解决方案
-
在拖拽时对元素边界进行实时判断
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> * { margin: 0; padding: 0; } #oDiv { width: 100px; height: 100px; background-color: #000; position: absolute; } </style> </head> <body> 55555555555 <div id="oDiv"></div> <script> oDiv.onmousedown = function(e) { var ev = e || event; var left = ev.clientX - oDiv.offsetLeft, top = ev.clientY - oDiv.offsetTop; document.onmousemove = function(e) { var ev = e || event; var leftW = ev.clientX - left; var topH = ev.clientY - top; //左边不能超出 if (leftW < 0) { leftW = 0; } //上边不能超出 if (topH < 0) { topH = 0; } //右边不能超出 if (leftW > document.documentElement.clientWidth - oDiv.offsetWidth) { leftW = document.documentElement.clientWidth - oDiv.offsetWidth; } //下边不能超出 if (topH > document.documentElement.clientHeight - oDiv.offsetHeight) { topH = document.documentElement.clientHeight - oDiv.offsetHeight; } oDiv.style.left = leftW + 'px'; oDiv.style.top = topH + 'px'; } document.onmouseup = function(e) { document.onmousemove = null; document.onmouseup = null; } return false; } </script> </body> </html>
基于HTML5拖拽API实现拖拽
前序:一个典型的拖拽操作为用户用鼠标选中一个可拖动(draggable)元素,移动鼠标到一个可放置(droppable)元素上,然后松开鼠标。在操作期间,会触发事件,有些事件可能会被多次触发(比如drag和dragover事件)
-
可拖动元素
又称为源对象,是指我们点击之后准备拖动的对象(图片,容器,文字等元素)
-
可放置元素
又称为目标对象,是指可以放置源对象的区域
-
事件
Event On Event Handler Description drag ondrag 当拖动元素或选中的文本时触发 dragend ondragend 当拖拽操作结束时触发(比如松开鼠标或者按下“Ese”键) dragenter ondragenter 当拖动元素或选中的文本到一个可释放目标时触发 dragexit ondragexit 当元素变得不再是拖动操作的选中目标时触发 dragleave ondragleave 当拖动元素或选中的文本离开一个可释放目标上时触发 dragover ondragover 当元素或选中的文本拖到一个可释放目标时触发 dragstart ondragstart 当用户爱是拖动一个元素或选中的文本时触发 drop ondrop 当元素或选中的文本在可释放目标上释放时触发
HTML5为所有的拖动的相关事件提供了一个新的属性
-
源对象和目标对象的事件间传递数据
ev.dataTransfer{}// 数据传递对象 -
源对象上的事件处理中保存数据
ev.dataTransfer.setData(key,value)// key,value必须都是字符串类型 -
目标对象上的事件处理中读取数据
var value = ev.dataTransfer.getData(key) -
兼容性
全部代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style type="text/css">
#thatDiv {
width: 500px;
height: 100px;
border: 1px solid red;
position: relative;
}
#thisDiv {
width: 500px;
height: 100px;
border: 1px solid black;
margin-bottom: 20px;
}
#tarDiv,
#tarDiv1,
#tarDiv2,
#tarDiv3,
#tarDiv4 {
float: left;
width: 50px;
height: 50px;
background-color: #000;
border: 1px #fff solid;
}
.tarDiv {
color: #fff;
text-align: center;
line-height: 50px;
}
</style>
</head>
<body>
<div id="thisDiv">
<div id="tarDiv" class="tarDiv" draggable="true">1</div>
<div id="tarDiv1" class="tarDiv" draggable="true">2</div>
<div id="tarDiv2" class="tarDiv" draggable="true">3</div>
<div id="tarDiv3" class="tarDiv" draggable="true">4</div>
<div id="tarDiv4" class="tarDiv" draggable="true">5</div>
</div>
<div id="thatDiv"></div>
<script type="text/javascript">
var tarDiv = document.getElementsByClassName("tarDiv");
var thisDiv = document.getElementById("thisDiv");
var thatDiv = document.getElementById("thatDiv");
thisDiv.ondragstart = function(ev) {
var ev = ev || window.event;
ev.dataTransfer.setData("text", ev.target.id); //将被拖拽的元素的id存入dataTransfer对象中
window.thisId = ev.target.id;
ev.dataTransfer.effectAllowed = "copy";
}
thatDiv.ondragover = function(ev) { //阻止dragover的默认事件
var ev = ev || window.event;
if (typeof ev.preventDefault == "function") {
ev.preventDefault();
} else {
ev.returnValue = false;
}
var div = document.getElementById(window.thisId);
thatDiv.appendChild(div);
div.style.cssText = "border:1px #fff dashed;";
ev.preventDefault();
ev.dataTransfer.dropEffect = "copy";
}
thatDiv.ondragenter = function(ev) { //阻止dragenter的默认事件
var ev = ev || window.event;
if (typeof ev.preventDefault == "function") {
ev.preventDefault();
} else {
ev.returnValue = false;
}
}
thatDiv.ondragleave = function(ev) {
var ev = ev || window.event;
var removeDiv = document.getElementById(window.thisId);
thatDiv.removeChild(removeDiv);
thisDiv.appendChild(removeDiv);
removeDiv.style.cssText = "border:1px #fff solid;";
ev.preventDefault();
}
thatDiv.ondrop = function(ev) {
var ev = ev || window.event;
var divId = ev.dataTransfer.getData("Text"); //从dataTransfer对象中取出数据
if (typeof ev.preventDefault == "function") { //阻止drop事件的默认行为
ev.preventDefault();
} else {
ev.returnValue = false;
}
var moveDiv = document.getElementById(divId);
thatDiv.appendChild(moveDiv);
moveDiv.setAttribute('draggable', 'false');
moveDiv.style.cssText = "border:1px #fff solid;";
}
</script>
</body>
</html>