检测碰撞并吸附 效果

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script type="text/javascript" src="admin/ceshi2/js/jquery-1.9.1.min.js"></script>
</head>
<style type="text/css">
    .div1{
        width: 100px;
        height: 100px;
        background: red;
        position: absolute;
        top:200px;
        left: 200px;
    }
    .div2{
        width: 100px;
        height: 100px;
        background: red;
        position: absolute;
        top:200px;
        left: 400px;
    }
    .div3{
        width: 100px;
        height: 100px;
        background: red;
        position: absolute;
        top:200px;
        left: 600px;
    }
    .div4{
        width: 100px;
        height: 100px;
        background: red;
        position: absolute;
        top:400px;
        left: 200px;
    }
    .div5{
        width: 100px;
        height: 100px;
        background: red;
        position: absolute;
        top:400px;
        left: 400px;
    }
    .div6{
        width: 100px;
        height: 100px;
        background: red;
        position: absolute;
        top:400px;
        left: 600px;
    }
    .active{
        background:blue;
    }
</style>
<body>
    <div class="div1 box">1</div>
    <div class="div2 box">2</div>
    <div class="div3 box">3</div>
    <div class="div4 box1">3</div>
    <div class="div5 box1">2</div>
    <div class="div6 box1">1</div>
</body>
<script type="text/javascript">
    var oBox = $('.box');
    var oBox1 = $('.box1');
    var aPos = [];//存储不能拖动的DIV初始位置;
    var aPos1 = [];//存储可以拖动的DIV初始位置;
    var biaoshi               //全局变量标识true表示已经碰撞false表示未碰撞到
    var LL                    //表示所有被碰撞过的div距离被拖动元素最近的定位Left值;
    var TT                    //表示所有被碰撞过的div距离被拖动元素最近的定位Top值;
    var num                   //被拖动元素的索引值,当没有碰撞元素时被拖动元素要回到自身最初是位置通过这个索引找到对应位置;
    for(var i = 0;i<oBox1.length;i++){
        drag(oBox1[i]);//传参,分别给三个可以被拖动的元素加方法;
    } 
    for(var i = 0;i<oBox.length;i++){
        oBox[i].setAttribute('index',i)//设置不能拖动的DIV索引值;
        aPos[i] = {//存储不能拖动的DIV初始位置程序;
            left:oBox[i].offsetLeft,
            top:oBox[i].offsetTop,
            right: oBox[i].offsetLeft + oBox[i].offsetWidth,
            bottom:oBox[i].offsetTop + oBox[i].offsetHeight
        }
    } 
    for(var i = 0;i<oBox1.length;i++){
        oBox1[i].setAttribute('index',i)//设置被拖动的DIV索引值;
        aPos1[i] = {//存储可以拖动的DIV初始位置程序;
            left:oBox1[i].offsetLeft,
            top:oBox1[i].offsetTop
        }
    } 
    function drag(obj){
        obj.onmousedown = function(ev){
            var MinBoj = null;//表示所有被碰撞过的div距离被拖动元素最近的元素变量;
            num = obj.getAttribute('index');//获取当前被拖动元素的索引值
            obj.style.transition = '0s';
            var Domarr = [];//存储所有被碰撞过的元素
            var oEvent = ev||window.event;
            var disX = oEvent.clientX - obj.offsetLeft;
            var disY = oEvent.clientY - obj.offsetTop;
            if(obj.setCapture){
                obj.setCapture();
            }
            document.onmousemove = function(ev){
                for (var i = 0;i<oBox.length;i++) {//当已经吸附的元素被再次点击且做了拖拽那么就要清除之前对应目标元素的KKK属性,方便其他元素再次吸附
                    if (oBox[i].getAttribute('kkk')==num) {
                        oBox[i].removeAttribute('kkk');
                    }
                }
                obj.removeAttribute('kkk');//为了清除之前已经吸附的元素身上的属性KKK,以免造成程序混乱
                biaoshi = 0;//表示没有碰撞
                var MaxNumber = 9999999999999;//最大值
                var oEvent = ev||window.event;
                //获取一下拖动元素的上下左右的距离。
                var l1 = oEvent.clientX - disX;
                var t1 = oEvent.clientY - disY;
                var r1 = l1 + obj.offsetWidth;
                var b1 = t1 + obj.offsetHeight;
                
                //获取一下在被拖动时元素的left和top值以保证元素可以随着鼠标移动。
                obj.style.left = l1 + 'px';
                obj.style.top = t1 + 'px';
                //循环判断被拖动元素是否和目标元素发生碰撞如果发生碰撞就将biaoshi=1
                for (var i=0;i<oBox.length;i++) {
                    if((r1<aPos[i].left&&aPos[i].left-r1>20) || (b1<aPos[i].top&&aPos[i].top-b1>20) || (l1>aPos[i].right&&l1-aPos[i].right>20) || (t1 > aPos[i].bottom&&t1-aPos[i].bottom>20)){//没碰到的
                        oBox[i].setAttribute('index',i)
                    }else{
                        Domarr.push(oBox[i])//将所有被碰撞过的元素添加到一个新的数组中
                        biaoshi = 1;
                    }
                }
                //计算所有被碰撞过的元素,到底哪一个离被拖动的元素最近,找到之后将其记录下来
                for(var j=0;j<Domarr.length;j++){
                    var L = Math.abs(obj.offsetLeft - Domarr[j].offsetLeft);        
                    var T = Math.abs(obj.offsetTop - Domarr[j].offsetTop);
                    var sqrt = Math.sqrt(L*L+T*T);
                    if(MaxNumber > sqrt){
                        MaxNumber = sqrt;
                        MinBoj = Domarr[j];    
                    }
                    if(MinBoj){
                        var num1 = Domarr[Domarr.length-1].getAttribute('index');//拿到最终离被拖动元素最近的DIV,并获取到他的索引值
                        LL = aPos[num1].left;//通过索引值找到被拖动元素最终的定位left和top值;
                        TT = aPos[num1].top;//
                    }
                }
            }
            document.onmouseup = function(){
                if (MinBoj) {//如果有最终目标就走true否则走false
                    if (biaoshi == 1&&!MinBoj.getAttribute('kkk')) {//如果biaoshi为1,并且最终目标元素上没有自定义属性kkk表示可以吸附否则表示该目标元素已经被其他元素吸附不可重复吸附
                        Domarr[Domarr.length-1].setAttribute('kkk',num);//给目标元素加上属性KKK表示他是已经被吸附的元素
                        obj.style.top = TT+'px';
                        obj.style.left = LL+'px';
                        obj.style.transition = '0.5s';
                        obj.setAttribute('kkk',num);//给被拖动元素加上自定义属性KKK以便下次拖动知道他是已经吸附的元素
                    }else{
                        obj.style.top = aPos1[num].top+'px';//如果不可吸附则被拖动元素回到初始位置
                        obj.style.left = aPos1[num].left+'px';
                        obj.style.transition = '0.5s';
                    }
                } else{
                    if (obj.getAttribute('kkk')) {//如果没有目标元素并且被点击元素身上有自定义属性KKK表示他是已经吸附的元素,并且没有做拖动他的位置应还是被吸附元素的定位值
                        obj.style.top = TT+'px';
                        obj.style.left = LL+'px';
                        obj.style.transition = '0.5s';
                    } else{//如果没有目标元素,被点击且没有自定义属性KKK表示他本身就是初始位置
                        obj.style.top = aPos1[num].top+'px';
                        obj.style.left = aPos1[num].left+'px';
                        obj.style.transition = '0.5s';
                    }    
                }
                document.onmousemove = null;
                document.onmouseup = null;
    
                if(obj.releaseCapture){
                    obj.releaseCapture();
                }
            }
            return false;
        }
    }
</script>

</html>

    
原文地址:https://www.cnblogs.com/xiangxuemei/p/9377341.html