1. 效果
可拖动到任意一个框内


2. 原理
- 碰撞检测
- 碰撞到的框加上relative定位
- getBoundingClientRect()---获取元素到浏览器左上角的位置
3. 代码
html
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<p class="drag">拖动我</p>
css
*{
margin: 0;
padding: 0;
list-style: none;
-webkit-user-select: none;
}
li{
width: 100px;
height: 100px;
border: 1px solid #000000;
float: left;
margin: 20px 30px;
}
.drag{
width: 50px;
/*给拖动对象定位 --- 一定要加!*/
position: absolute;
}
js
获取对象
let ali = document.querySelectorAll("li");
let dragEl = document.querySelector(".drag");
调用函数
//实现拖动元素到指定容器中
drag(dragEl,function(){//鼠标松开时 --- cb1
for(let i=0;i<ali.length;i++){
let res = bump(dragEl,ali[i]);// 判断碰撞/碰撞 得到返回的布尔值
if(res){//如果松开后碰撞的话
console.log(res);
success(dragEl,ali[i]);//调用success函数 --- 给该框定位
}
ali[i].style.border = "1px solid #000";//设置鼠标松开时边框变回黑色
}
for(let i=0;i<ali.length;i++){
if(ali[i].children.length>0){/*如果原来的容器里有拖动对象,
再拖动时不在任何一个容器内,则将拖动对象放回原来的容器中*/
ali[i].style.position = "relative";
dragEl.style.left = "0px";
dragEl.style.top = "0px";
}
}
},function(){//鼠标按下时 --- cb2
/*设置鼠标按下时,拖动对象相对浏览器窗口的位置,
此后交给鼠标移动时的函数,并且将全部目标容器的定位信息设置为正常*/
dragEl.style.left = dragEl.getBoundingClientRect().left+"px";
dragEl.style.top = dragEl.getBoundingClientRect().top+"px";
for(let i=0;i<ali.length;i++){//这个不能跟上面两行代码换序!
ali[i].style.position = "static";
}
},function(){//鼠标移动时 --- 边框变色 --- cb3
for(let i=0;i<ali.length;i++){
let res = bump(dragEl,ali[i]);//判断是否碰撞到
if(res){
ali[i].style.border = "1px dashed red";
}else{
ali[i].style.border = "1px solid #000";
}
}
})
封装函数
//拖动函数
//在传参的时候可以设置默认值
/*
* drag:拖动函数
* obj:拖动的对象
* cb1:拖动对象时鼠标松开的回调函数
* cb2:点击拖动对象的是回调函数
* cb3:拖动对象时的回调函数
*
*/
function drag(obj,cb1=function(){},cb2=function(){},cb3=function(){}){
obj.addEventListener("mousedown",(e)=>{
let x = e.clientX,
y = e.clientY,
_left = obj.getBoundingClientRect().left,
_top = obj.getBoundingClientRect().top;
cb2();//***
document.onmousemove = function(e){
obj.style.top = e.clientY - (y-_top)+"px";
obj.style.left = e.clientX - (x-_left)+"px";
cb3();//***
}
document.onmouseup = function(){
cb1();//***
document.onmousemove = null;
document.onmouseup = null;
}
})
}
//碰撞检测函数
function bump(obj1,obj2){
//offsetLeft,offsetTop是相对于其祖先元素中 ***
//具有定位信息的那个元素的左上角的位置
//想要获取元素到浏览器左上角的位置
//getBoundingClientRect()
// console.log(obj1.offsetLeft);
let obj1Pos = obj1.getBoundingClientRect();
let obj2Pos = obj2.getBoundingClientRect();
let t1 = obj1.offsetTop,
r1 = obj1Pos.right,
b1 = obj1Pos.bottom,
l1 = obj1.offsetLeft;
let t2 = obj2.offsetTop,
r2 = obj2Pos.right,
b2 = obj2Pos.bottom,
l2 = obj2.offsetLeft;
if(t1>b2||r1<l2||b1<t2||l1>r2){//没碰撞
return false;
}else{//碰撞到
return true;
}
}
//函数: --- 设置 拖动对象相对于 目标容器 定位在最左上角
function success(obj,objBox){//(拖动对象,目标容器)
objBox.appendChild(obj);//拿出来放回去
objBox.style.position = "relative";
obj.style.left = "0px";
obj.style.top = "0px"
}
网友评论