照片牆-拖拽交換

效果圖

在這裏插入圖片描述
在這裏插入圖片描述

html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }

        ul {
            width: 480px;
            height: 640px;
            margin: 10px auto;
            background: yellow;
            padding: 10px;
            position: relative;
            list-style: none;
        }

        ul li {
            width: 150px;
            height: 150px;
            margin: 5px;
            float: left;
            background: lightgreen;
            cursor: move;
            /*position: relative;*/
            /*相對父級;通過getComputedStyle獲取的是相對於自身的位置的left和top;*/
        }

        ul li img {
            width: 100%;
            height: 100%;
            user-select: none;
            pointer-events: none;
        }
    </style>
</head>

<body>
    <ul>
    <li><img src="../day02/images/images/23.jpg"></li>
    <li><img src="../day02/images/images/22.jpg"></li>
    <li><img src="../day02/images/images/21.jpg"></li>
    <li><img src="../day02/images/images/20.jpg"></li>
    <li><img src="../day02/images/images/19.jpg"></li>
    <li><img src="../day02/images/images/18.jpg"></li>
    <li><img src="../day02/images/images/17.jpg"></li>
    <li><img src="../day02/images/images/16.jpg"></li>
    <li><img src="../day02/images/images/15.jpg"></li>
    <li><img src="../day02/images/images/14.jpg"></li>
    <li><img src="../day02/images/images/13.jpg"></li>
    <li><img src="../day02/images/images/12.jpg"></li>
    </ul>
    <script src="event.js"></script>
    <script>
        let oLis = document.getElementsByTagName("li");
        // 循環每一個li;讓其有拖拽效果;
        // 通過倒序,先給最後一張加position,那麼前面幾張位置是不受影響的;
        // offsetLeft : 獲取是當前盒子的外邊框到父級參照物的內邊框的距離,包含margin值;這樣會導致設置的left值偏大
        for (let i = oLis.length - 1; i >= 0; i--) {
            oLis[i].style.left = oLis[i].offsetLeft - 5 + "px";
            oLis[i].style.top = oLis[i].offsetTop - 5 + "px";
            oLis[i].style.position = "absolute"; //
            // 第一個迅速脫離文檔流;第二個元素會跑到第一個位置上;
            new Drag(oLis[i]).on("selfdown", changeIndex).on("selfmove", isHit).on("selfup", changePosi);
        }
        let zIndex = 0;
        // 增加拖拽元素的索引;
        function changeIndex() {
            // 保證當前拖拽的元素z-index永遠是最大的;
            this.ele.style.zIndex = ++zIndex;
        }
        // 碰撞檢測
        function isHit() {
            // this--> Drag的實例;上的ele屬性就是被拖拽的元素;
            let curLi = this.ele;
            this.hit = [];
            for (let i = 0; i < oLis.length; i++) {
                if (curLi === oLis[i]) continue; // 和自己沒必要進行檢測;
                if (curLi.offsetLeft + curLi.offsetWidth < oLis[i].offsetLeft || curLi.offsetTop + curLi.offsetHeight <
                    oLis[i].offsetTop || curLi.offsetTop > oLis[i].offsetTop + oLis[i].offsetHeight || curLi
                    .offsetLeft > oLis[i].offsetLeft + oLis[i].offsetWidth) {
                    // 只要滿足其中一個條件,那麼說明這個拖拽的盒子和li沒有重合的部分;沒有碰撞;
                    // 說明沒碰到
                    oLis[i].style.background = "";
                } else {
                    oLis[i].style.background = "pink";
                    this.hit.push(oLis[i]); // 把有交集的元素放入hit這個數組中;
                }
            }
        }

        function changePosi() {
            //this
            let ary = this.hit;
            let curLi = this.ele;
            if (ary) {
                for (let i = 0; i < ary.length; i++) {
                    let cur = ary[i];
                    // 計算出左上角點之間的距離的平方;
                    cur.distance = Math.pow(cur.offsetLeft - curLi.offsetLeft, 2) + Math.pow(cur.offsetTop - curLi
                        .offsetTop, 2);
                    cur.style.background = "";
                }
            };
            // 對數組的distance進行排序;找出最小值;
            ary.sort(function (a, b) {
                return a.distance - b.distance;
            })
            // 實現位置的交換
            if (ary[0]) {
                this.ele.style.left = ary[0].style.left;
                this.ele.style.top = ary[0].style.top;
                ary[0].style.left = this.l + "px";
                ary[0].style.top = this.t + "px";
            } else {
                // 如果沒有任何碰撞的元素,直接設置原有的樣式;
                this.ele.style.left = this.l + "px";
                this.ele.style.top = this.t + "px";
            }
            this.hit = []; // 清空hit;
        }
    </script>
</body>

</html>

event.js

function EventFire() {}
EventFire.prototype.on=function (type,fn) {
    // 把方法訂閱到這個EventFire這個類的實例上;
    if(!this[type]){
        // 第一次執行,給obj新增鍵值對,並且屬性值是[];
        this[type]=[];
    }
    let ary = this[type];
    //遍歷ary中的數組成員,判斷是否綁定過;
    for(let i=0;i<ary.length;i++){
        if(ary[i]===fn){
            return;
        }
    }
    ary.push(fn);
    // 爲了實現鏈式調用on訂閱的方法;
    return this;
}
EventFire.prototype.emit=function (type) {
    let a = this[type];
    if(a){//如果是undefined,不進循環
        for(let i=0;i<a.length;i++){
            if(typeof a[i]==="function"){
                a[i].call(this);
            }
        }
    }
}
EventFire.prototype.off=function (type,fn) {
    let ary = this[type];
    for(let i=0;i<ary.length;i++){
        if(fn===ary[i]){
            //ary.splice(i,1);數組塌陷;
            ary[i]=null;
            return;
        }
    }
}
function Drag(ele) {
    // this-->實例;Drag的一個實例
    // 把元素放在Drag的實例上;
    this.ele = ele;
    this.ele.onmousedown=this.down.bind(this);
}
// 原型繼承
Drag.prototype=new EventFire();
Drag.prototype.down=function (e) {
    // console.log(this);// this--> Drag的實例
    this.x=e.clientX;
    this.y=e.clientY;
    this.l = parseFloat(getComputedStyle(this.ele).left);
    this.t = parseFloat(getComputedStyle(this.ele).top);
    document.onmousemove=this.move.bind(this);
    document.onmouseup = this.up.bind(this);
    this.emit("selfdown");
}
Drag.prototype.move=function (e) {
    let changeX = e.clientX-this.x+this.l;
    let changeY = e.clientY-this.y+this.t;
    this.ele.style.left = changeX+"px";
    this.ele.style.top= changeY+"px";
    this.emit("selfmove")
}
Drag.prototype.up = function () {
    document.onmousemove=null;
    document.onmouseup =null;
    this.emit("selfup");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章