碰撞檢測

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        ul{
            list-style:none;
            width: 900px;
            height: 500px;
            margin:50px auto;
        }
        img{
            display:block;
            width: 100%;
            height: 100%;
        }
        li{
            float:left;
            width: 200px;
            height: 150px;
            margin:10px;
            border:1px solid blue;
            cursor:move;
        }
        .active{
            border:1px dashed #ccc;
        }
    </style>
</head>
<body>
    <ul id="list">
        <li><img src="./img/1.jpg" alt=""></li>
        <li><img src="./img/2.jpg" alt=""></li>
        <li><img src="./img/3.jpg" alt=""></li>
        <li><img src="./img/4.jpg" alt=""></li>
        <li><img src="./img/5.jpg" alt=""></li>
        <li><img src="./img/6.jpg" alt=""></li>
        <li><img src="./img/7.jpg" alt=""></li>
        <li><img src="./img/8.jpg" alt=""></li>
        <li><img src="./img/9.jpg" alt=""></li>
        <li><img src="./img/10.jpg" alt=""></li>
        <li><img src="./img/11.jpg" alt=""></li>
        <li><img src="./img/12.jpg" alt=""></li>
    </ul>

    <script src="./base.js"></script>
    <script>

    /*思路:封裝一個拖拽的函數,使每個對象可以實現拖拽
        (1)分析:拖拽的實現需要絕對定位脫離文檔流
            問題:給css設置position:absolute;圖片重疊在一處
            解決:先通過循環利用每個元素的offsetLeft以及offsetTop記住每個元素的位置,然後賦值給各個元素的left和top值,將所有元素的left和top值設置好之後再給元素脫離文檔流 並且清除元素的margin值,循環調用拖拽函數.

        (2)如何讓元素擡起鼠標的時候回到原來的位置?
            解決:調用move函數,move(操作的對象,回到的位置(json對象),回調函數);
            問題:位置如何找?
            解決:循環把各個元素的位置按照對象的形式{"left":值,"top":值}保存在數組裏面,可以通過下標來訪到每個元素的位置

        (3)層級問題
            解決:利用計數器讓點擊元素層級++;

        (4)碰撞檢測
            思路:封裝一個碰撞的函數,返回碰撞最多那個元素的下標(因爲咱們要通過下標找位置);
                找到兩個元素:①拖拽元素obj②碰撞元素(得循壞查找拖拽元素是否佔了人家的位置){要除去本身}
                找沒碰的範圍,排除沒碰的範圍剩下的就是碰了
                左:boxL+boxW<objL
                右:objL+objW<boxL
                上:boxT+boxH<objT
                下:objT+objH<boxT


        (5)找碰撞最多的元素(即左上角對角線最短的)以及這個元素的下標
            問題:因爲要檢測的碰撞元素時除本身外的其他所有元素
                有可能它同時跟好多元素進行碰撞
                咱們要在一堆裏面找距離最小的
                找最小距離的方法:先假設某個數最小完後跟後面一堆數進行比較,如果後面出現比假設的最小數還小的數,那麼將這個數賦給最小數,這個l對應哪個元素的下標i賦給最小數的下標
                在循環結束找到最小值的下標返回;
                在鼠標擡起的時候,調用碰撞的函數bb(obj),將它返回值保存在_index裏面

        (6)換位置
            對象(aLi)                    下標          位置(arr)

            拖拽元素aLi[index](obj)      index             arr[index]
            碰撞元素aLi[_index]          _index         arr[_index]
 

            如果沒碰到(即返回值-1),回到拖拽元素自己的位置move(obj,arr[index]);
            如果碰到了,進行位置交換move(obj,arr[_index])
                                       move(aLi[_index],arr[index])
            同時要把保存位置的數組裏面的位置進行交換*/

        var oList=document.getElementById("list");
        var aLi=oList.getElementsByTagName("li");
        var zIndex=1;
        var arr=[];
        for(var i=0;i<aLi.length;i++){
            aLi[i].style.left=aLi[i].offsetLeft+"px";
            aLi[i].style.top=aLi[i].offsetTop+"px";
            arr.push({"left":aLi[i].offsetLeft,"top":aLi[i].offsetTop});  
        }
        for(var i=0;i<aLi.length;i++){
            aLi[i].style.position="absolute";
            aLi[i].style.margin=0;
            getDay(aLi[i],i);
        }


        function getDay(obj,index){
            obj.onmousedown=function(ev){
                obj.style.zIndex=zIndex++;
                var evt=ev||window.event;
                var dx=evt.offsetX;
                var dy=evt.offsetY;
                document.onmousemove=function(ev){
                    var evt=ev||window.event;
                    var x=evt.clientX; 
                    var y=evt.clientY;
                    obj.style.left=x-dx+"px";
                    obj.style.top=y-dy+"px";
                    ww=PZ(obj);
                    for(var i=0;i<aLi.length;i++){
                        aLi[i].className="";
                    }
                    if(ww!=-1){
                        aLi[ww].className="active";
                    }
                    return false;
                }
                document.onmouseup=function(){
                    document.onmousemove=null;
                    ww=PZ(obj);
                    if(ww==-1){
                        move(obj,arr[index]);
                    }else{
                        move(obj,arr[ww]);
                        move(aLi[ww],arr[index]);//元素和位置
                        //出現問題,都給第一張換位
                        var timep=arr[index];
                        arr[index]=arr[ww];
                        arr[ww]=timep;
                        for(var i=0;i<aLi.length;i++){
                            aLi[i].className="";
                        }
                        
                    }
                    return false;
                }
            }
        }

        function PZ(obj){
            var oL=obj.offsetLeft;
            var oT=obj.offsetTop;
            var oW=obj.offsetWidth;
            var oH=obj.offsetHeight;
            var min=100000;
            var mIndex=-1;

            for(var i=0;i<aLi.length;i++){
                //不能跟本身比較
                if(aLi[i]==obj){
                    continue;
                }
                var aL=aLi[i].offsetLeft;
                var aT=aLi[i].offsetTop;
                var aW=aLi[i].offsetWidth;
                var aH=aLi[i].offsetHeight;
                //找一個判斷一個
                if(oL+oW<aL||oL>aL+aW || oT+oH<aT || oT>aT+aH){
                    //沒碰的
                }else{
                    /*console.log("碰到了"+i);*/
                    var a=oL-aL;
                    var b=aT-oT;
                    var l=Math.sqrt(a*a+b*b);
                    if(l<min){
                        min=l;
                        mIndex=i;
                    }
                }
            }
            return mIndex;
        }
    </script>
</body>
</html>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章