美文网首页JS基础前端Javascript
JS 实现拖拽之 - 九宫格拖拽

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

作者: CondorHero | 来源:发表于2019-07-02 15:32 被阅读52次
    九宫格.gif

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

    • 鼠标拖拽模型实现
    • li 盒子进行绝对定位
    • 批量监听和批量操作 li 盒子
    • 判断条件为移动盒子的 top 和 left 在另一个盒子之内。
    <!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 属性,当需要交换位置的时候就可以专心的交换盒子元素属性值。这也算是闭包的最佳实践应用。

    相关文章

      网友评论

        本文标题:JS 实现拖拽之 - 九宫格拖拽

        本文链接:https://www.haomeiwen.com/subject/ilizcctx.html