JS基础前端Javascript

JS 实现拖拽之 - 九宫格拖拽

2019-07-02  本文已影响52人  CondorHero
九宫格.gif

实现思路和需要掌握的技术:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>九宫格</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        ul{
            position: relative;
            list-style:none;
            width: 1062px;
            height: 1500px;
            border: 1px solid #333;
            margin:0 auto;
        }
        ul li{
            position: absolute;
            width: 354px;
            height: 500px;
            background:url("animate.jpg") no-repeat;
            cursor: pointer;
        }
        /*拖拽的时候让拖拽的图片置于其他图片上面*/
        .active{
            z-index:1;
        }
    </style>
</head>
<body>
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</body>
</html>
<script>
    //得到元素
    var uls = document.querySelector("ul");
    var lis = uls.querySelectorAll("li");

    // 批量添加监听
    for(var i = 0;i < lis.length;i++){
        // 批量放置li盒子的位置和里面的图片
        lis[i].style.left = (i % 3) * 354 + "px";
        lis[i].style.top = parseInt(i / 3) * 500 + "px";
        lis[i].style.backgroundPosition = -(i % 3) * 354 + "px " + -parseInt(i / 3) * 500 + "px";
        // 闭包的影响属性法备份 i
        lis[i].index = i;
        // 鼠标按下
        lis[i].onmousedown = function(event){
            // 兼容IE
            event = event || window.event;
            // 鼠标到每个li盒子内层最顶端和最左端的位置
            var lisx = event.clientX - this.offsetLeft;
            var lisy = event.clientY - this.offsetTop;
            // 备份this
            var self = this;
            document.onmousemove = function(event){
                // console.log(self);//如果是this这时this指代的是document
                // 兼容IE
                event = event || window.event;
                // li盒子到它的offsetparent的距离,就是离li最近定位的盒子
                lisL = event.clientX - lisx;
                lisT = event.clientY - lisy;
                self.className = "active";
                // 改变移动盒子的定位,做到鼠标跟随
                self.style.left = lisL + "px";
                self.style.top = lisT + "px";
            }
            // 鼠标抬起
            document.onmouseup = function(event){
                // 兼容IE
                event = event || window.event;
                // 清除鼠标移动时间
                document.onmousemove = null;
                // 移出每个添加类名的元素
                self.className = "";
                // 批量遍历每个盒子是否满足交换条件
                for(var j = 0;j < lis.length;j++){
                    if(lis[j].offsetLeft + lis[j].offsetWidth > self.offsetLeft && lis[j].offsetTop + lis[j].offsetHeight > self.offsetTop && lis[j].offsetLeft < self.offsetLeft && lis[j].offsetTop < self.offsetTop){
                        // console.log(self.index)
                        // 满足条件的时候交换两个盒子元素的属性值 index
                        var temp = lis[j].index;
                        lis[j].index = self.index;
                        self.index = temp;
                        // 交换位置
                        lis[j].style.left = (lis[j].index % 3) * 354 + "px";
                        lis[j].style.top = parseInt(lis[j].index / 3) * 500 + "px";
                        // 如果找到就退出循环。不在进行查找
                        break;
                    }
                }
                // 这时在改变移动盒子的位置
                // 本来是放在for循环里面的,但是拿出来可以防止盒子不在监听位置的时候
                // 也就是index未改变的时候,会回到自己的原位置
                self.style.left = (self.index % 3) * 354 + "px";
                self.style.top = parseInt(self.index / 3) * 500 + "px";
            }
            // 防止浏览器的默认事件
            // 例如拖拽时文字选中
            return false;
        }
    }
</script>

实战心得:最难得莫过于交换过程中如何更改两个盒子的位置。如果提前知道思路当然很快就能想起来解决方法,但是难就难在你的动动手慢慢实践出来,出来之后记住类似的套路。

每个盒子的 li 的定位采用横着排的求余,竖着排的除。for 循环出现的 i 就是改变位置的关键,让 i 绑定到元素上。这时候就可以给元素一个 index 属性,当需要交换位置的时候就可以专心的交换盒子元素属性值。这也算是闭包的最佳实践应用。

上一篇下一篇

猜你喜欢

热点阅读