这个问题之前在面试的时候有遇到过,现在整理一下,这样也能更好的理解事件流。
拖拽的原理:
(1)鼠标和div的相对距离不变
(2)三大事件:onmousedown(选择元素) -> onmousemove(移动元素) -> onmouseup(释放元素)
(3)把拖拽加到document
#div1{
width: 100px;
height: 100px;
position: absolute;
background-color: red;
}
<div id="div1"></div>
var oDiv = document.getElementById('div1');
oDiv.onmousedown = function(ev){
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
document.onmousemove = function(ev){ //不是oDiv.onmousemove的原因是防止拖快的话鼠标脱离div,div就不跟随
var ev = ev || event;
oDiv.style.left = ev.clientX - disX + 'px';
oDiv.style.top = ev.clientY - disY + 'px';
}
document.onmouseup = function(){
document.onmousemove = document.onmouseup = null; //释放 不是oDiv.onmouseup和oDiv.onmousemove的原因是为了防止当div被遮盖时释放鼠标(onmouseup)无效(因为释放鼠标是触发遮盖的那层的)
}
}
拖拽的问题以及解决办法:
(1)拖拽的时候,如果有文字被选中,会产生问题。
原因:当鼠标按下的时候,如果页面中有文字被选中,会触发浏览器的默认拖拽文字的效果。
解决方法:
标准下:在onmousedown事件的函数里面添加return false;
非标准IE下:通过在ie下设置全局捕获,用setCapture()方法曲线救国
(2)拖拽图片会有问题,原因和解决方法同
全局捕获:
方法:元素.setCapture();
当我们给一个元素设置全局捕获以后,这个元素就会监听后续发生的所有事件,当有事件发生的时候,就会被当前设置了全局捕获的元素所触发
兼容性问题:
IE:有,并且有效果
ff:有,但是没效果
chrome:没有这个方法
与之对应的释放全局捕获的方法是:元素.releaseCapture();
修改后的代码
var oDiv = document.getElementById('div1');
oDiv.onmousedown = function(ev) {
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
if ( oDiv.setCapture ) {
oDiv.setCapture();
} //兼容代码
document.onmousemove = function(ev) {
var ev = ev || event;
oDiv.style.left = ev.clientX - disX + 'px';
oDiv.style.top = ev.clientY - disY + 'px';
}
document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
//释放全局捕获 releaseCapture();
if ( oDiv.releaseCapture ) {
oDiv.releaseCapture();
} //兼容代码
}
return false; //阻止浏览器的默认行为
}
拖拽函数封装:
function drag(obj) {
obj.onmousedown = function(ev) {
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
if ( obj.setCapture ) {
obj.setCapture();
}
document.onmousemove = function(ev) {
var ev = ev || event;
obj.style.left = ev.clientX - disX + 'px';
obj.style.top = ev.clientY - disY + 'px';
}
document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
//释放全局捕获 releaseCapture();
if ( obj.releaseCapture ) {
obj.releaseCapture();
}
}
return false;
}
}
限制范围的拖拽:
function drag(obj){
obj.onmousedown = function(ev){
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
if(obj.setCapture){
obj.setCapture();
}
document.onmousemove = function(ev){
var ev = ev || event;
var L = ev.clientX - disX;
var T = ev.clientY - disY;
// 限制拖拽范围在页面内
if(L < 0){
L = 0;
} else if( L > document.documentElement.clientWidth - obj.offsetWidth){
L = document.documentElement.clientWidth - obj.offsetWidth;
}
if(T < 0){
T = 0;
} else if(T > document.documentElement.clientHeight - obj.offsetHeight){
T = document.documentElement.clientHeight - obj.offsetHeight;
}
obj.style.left = L + 'px';
obj.style.top = T + 'px';
}
document.onmouseup = function(){
document.onmousemove = document.onmouseup = null;
if(obj.releaseCapture){
obj.releaseCapture();
}
}
return false;
}
}
磁性吸附:
function drag(obj){
obj.onmousedown = function(ev){
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
if(obj.setCapture){
obj.setCapture();
}
document.onmousemove = function(ev){
var ev = ev || event;
var L = ev.clientX - disX;
var T = ev.clientY - disY;
// 限制拖拽范围在页面内
if(L < 100){ //只要把原来的0改为一个范围,例如:100,就实现了磁性吸附的效果
L = 0;
} else if( L > document.documentElement.clientWidth - obj.offsetWidth){
L = document.documentElement.clientWidth - obj.offsetWidth;
} //如果想让右边吸附的话将条件L > document.documentElement.clientWidth - obj.offsetWidth-100
if(T < 100){
T = 0;
} else if(T > document.documentElement.clientHeight - obj.offsetHeight){
T = document.documentElement.clientHeight - obj.offsetHeight;
}
obj.style.left = L + 'px';
obj.style.top = T + 'px';
}
document.onmouseup = function(){
document.onmousemove = document.onmouseup = null;
if(obj.releaseCapture){
obj.releaseCapture();
}
}
return false;
}
}
碰撞检测
#div1{
width: 100px;
height: 100px;
position: absolute;
background-color: red;
}
#img1{
position: absolute;
left: 500px;
top:200px;
}
<div id="div1"></div>
<img id="img1" src="1.jpg" >
var oDiv = document.getElementById('div1');
var oImg = document.getElementById('img1');
drag(oDiv);
function drag(obj) {
obj.onmousedown = function(ev) {
var ev = ev || event;
var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop;
if ( obj.setCapture ) {
obj.setCapture();
}
document.onmousemove = function(ev) {
var ev = ev || event;
var L = ev.clientX - disX;
var T = ev.clientY - disY;
//被拖动的元素的四条边
var L1 = L; //左边的left值
var R1 = L + obj.offsetWidth; //右边的left值
var T1 = T; //上边的top值
var B1 = T + obj.offsetHeight;//底边的top值
//被碰撞的元素的四条边(这个例子里面是img元素)
var L2 = oImg.offsetLeft;
var R2 = L2 + oImg.offsetWidth;
var T2 = oImg.offsetTop;
var B2 = T2 + oImg.offsetHeight;
if ( R1 < L2 || L1 > R2 || B1 < T2 || T1 > B2 ) {
oImg.src = '1.jpg';
} else {
oImg.src = '2.jpg';
}
obj.style.left = L + 'px';
obj.style.top = T + 'px';
}
document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
if ( obj.releaseCapture ) {
obj.releaseCapture();
}
}
return false;
}
}
拖拽改变层大小
var oDiv = document.getElementById('div1');
document.onmousemove = function(ev) {
moveDef(oDiv);
}
function moveDef(obj){
var ev = ev || event;
var disX = ev.clientX;
var disY = ev.clientY;
var disW = obj.offsetWidth;
var disL = obj.offsetLeft;
var disH = obj.offsetHeight;
var disT = obj.offsetTop;
if( disL - 5 < disX && disX < disL + 5 || disW + disL-5 < disX && disX< disW + disL + 5){
obj.style.cursor = 'w-resize';
}else if(disT - 5 < disY && disY < disT + 5 || disH + disT-5 < disY && disY< disH + disT + 5){
obj.style.cursor = 's-resize';
}else{
obj.style.cursor = 'default';
}
}
oDiv.onmousedown = function(ev) {
var _this = this;
var ev = ev || event;
var disX = ev.clientX;
var disY = ev.clientY;
var disW = this.offsetWidth;
var disL = this.offsetLeft;
var disH = this.offsetHeight;
var disT = this.offsetTop;
var b = '';
if ( disX > disL + disW - 5 ) {
b = 'right';
}
if ( disX < disL + 5 ) {
b = 'left';
}
if ( disY > disT + disH - 5 ) {
b = 'bootom';
}
if ( disY < disT + 5 ) {
b = 'top';
}
document.onmousemove = function(ev) {
var ev = ev || event;
switch( b ) {
case 'left':
oDiv.style.width = disW - ( ev.clientX - disX ) + 'px';
oDiv.style.left = disL + ( ev.clientX - disX ) + 'px';
break;
case 'right':
oDiv.style.width = disW + ( ev.clientX - disX ) + 'px';
break;
case 'top':
oDiv.style.height = disH - ( ev.clientY - disY ) + 'px';
oDiv.style.top = disT + ( ev.clientY - disY ) + 'px';
break;
case 'bootom':
oDiv.style.height = disH + ( ev.clientY - disY ) + 'px';
break;
}
}
document.onmouseup = function() {
document.onmousemove = function(ev) {
moveDef(oDiv);
};
document.onmouseup = null;
_this.style.cursor = 'default';
}
return false;
}