前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(Demo分享)利用JavaScript(JS)实现一个九宫格拖拽功能

(Demo分享)利用JavaScript(JS)实现一个九宫格拖拽功能

作者头像
Tz一号
发布2020-09-10 15:50:35
1.4K0
发布2020-09-10 15:50:35
举报
文章被收录于专栏:Tz一号Tz一号

利用JavaScript(JS)实现一个九宫格拖拽功能

Demo实现了对任意方格进行拖拽,可以交换位置,其中Demo-1利用了勾股定理判断距离!

Demo-1整体思路:

1.首先div实现自由移动,一定需要脱离标准文档流,所以我们给它使用绝对定位。

2.利用视觉欺骗,点击鼠标悬浮的其实是利用JS生成的一个Div,交换信息的两个Div并没有位置交换,只是把双方属性进行了交换。

3.利用了勾股定理去判断距离。

##效果图如下:

网页源代码:

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>九宫格拖拽</title>
</head>
<style type="text/css">
    #content{
        width: 300px;
        height:300px;
        margin: 0 auto;
        background: #F47564;
        position: relative;
    }
    #content div{
        width: 100px;
        height: 100px;
        float: left;
        line-height: 100px;
        text-align: center;
        font-size:40px;
        font-weight: 900;
        color: #fff;
        cursor: pointer;
        position: absolute;
    }
    #content div:nth-child(1){
        background-color: #f05b72;
        top:0;
        left: 0;
    }
    #content div:nth-child(2){
        background-color: #faa755;
        top:0;
        left:100px;
    }
    #content div:nth-child(3){
        background-color: #2585a6;
        top:0;
        left: 200px;
    }
    #content div:nth-child(4){
        background:#5ce4fd;
        top:100px;
        left: 0;
    }
    #content div:nth-child(5){
        background:#f61acf;
        top:100px;
        left: 100px;
    }
    #content div:nth-child(6){
        background:#3ef9bd;
        top:100px;
        left: 200px;
    }
    #content div:nth-child(7){
        background:#9af93e;
        top:200px;
        left: 0;
    }
    #content div:nth-child(8){
        background:#eef93e;
        top:200px;
        left: 100px;
    }
    #content div:nth-child(9){
        background:#f9843e;
        top:200px;
        left:200px;
    }
    #content .draging{
        position: absolute;
    }

</style>
<body>
<div id="content">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
</div>

<script type="text/javascript">
    var content = document.getElementById('content');
    var items = content.querySelectorAll('div');
    console.log(items);

    function itemBox(itemName){
        itemName.onmousedown = function(evt1){
            var e = evt1 || window.event;

            //在鼠标点下item的时候克隆一个新的一模一样的名为cloneDiv
            var cloneDiv = document.createElement('div');
            //把样式文字赋给克隆div
            cloneDiv.innerHTML = itemName.innerHTML;

            cloneDiv.style.backgroundColor = getComputedStyle(itemName).backgroundColor;

            //使克隆div的class名为draging,使克隆div加绝对定位position:absolute
            cloneDiv.className = 'draging';
            //克隆div的定位top left  和原div相同
            cloneDiv.style.top = itemName.offsetTop +'px';
            cloneDiv.style.left = itemName.offsetLeft+'px'

            //把kelongdiv加入到concent大盒子当中
            content.appendChild(cloneDiv);
            //算出鼠标点击克隆div时,鼠标在克隆div中的相对位置
            var offsetX = evt1.pageX - cloneDiv.offsetLeft;
            var offsetY = evt1.pageY - cloneDiv.offsetTop;
//              cloneDiv.style.zIndex = 10;

            //鼠标开始移动的时候
            document.onmousemove = function(evt){
                var e2 = evt || window.event;
                //克隆div定位的left  top   evt.pageX鼠标点相对于整个文档中的位置, offsetX鼠标相对于克隆div中的位置     二者相减就是克隆div相对于整个文档中的位置
                cloneDiv.style.left = evt.pageX - offsetX +'px';
                cloneDiv.style.top = evt.pageY -offsetY+'px'
            }

            //当鼠标松开的时候
            document.onmouseup = function(){
                //先把移动事件停止
                document.onmousemove = null;

                //需要判断 clonediv 的位置距 那个div 最近

                //先获取到content大盒子下所有的div
                var divs = content.getElementsByTagName('div');
                console.log(divs.length)
                //然后判断移动到位置距离哪一个最近


                var min = 800;//考虑到被拖拽的div拖拽到大盒子之外还能进行交换,距离设为大盒子外   方圆800px
                var minDiv = null;//设一个空的div用来交换位置
                for(var i=0;i<divs.length-1;i++){//遍历出除了鼠标移动的div外的所有的div  也就是length - 1
                    var div = divs[i];
                    //div cloneDiv

                    //distance(cloneDiv,div)返回值为c,c为两div之间的距离
                    var dis = distance(cloneDiv,div);//调用运用勾股定理进行比较距离的函数
                    if(dis <= min){//a^2 + b^2 和c^2比较
                        min = dis;
                        minDiv = div;
                    }
                }

                //把距离小的那个div的样式给拖拽走空出来的div  itemName


                //如果这样赋值的话target的innerHTML就会丢失都变成minDiv.innerHTML,所以的设一个中转变量,让两者交换。background同理
//                  minDiv.innerHTML = target.innerHTML;

                //两者样式交换,引入第三变量tmpInnerHTMl
                var tmpInnerHTMl = minDiv.innerHTML;

                minDiv.innerHTML = itemName.innerHTML;
                itemName.innerHTML = tmpInnerHTMl;

                //引入第三变量tmpColor
                var tmpColor = getComputedStyle(minDiv).backgroundColor;
                minDiv.style.backgroundColor = getComputedStyle(itemName).backgroundColor;

                itemName.style.backgroundColor = tmpColor;

                //删掉克隆元素
                content.removeChild(cloneDiv)
                document.onmouseup = null;//把鼠标松开后的操作清除

            }
            return false;
        }
    }

    //for循环使每一个item都调用itemBox()这个函数
    for(var i = 0; i < items.length; i++){
        itemBox(items[i]);
    }

    function distance(div1,div2) {
        //勾股定理 记录 两个元素的距离
        var a = div1.offsetLeft - div2.offsetLeft;
        var b = div1.offsetTop - div2.offsetTop;
        var c = Math.sqrt(a*a+b*b);  //利用勾股定理算出两个div的距离     a^2 + b^2 再开平方得出c
        return c;
    }
</script>
</body>
</html>

Demo-2整体思路(页面存在很多Bug,提供另一种思路,建议使用Demo1的方法):

1.首先div实现自由移动,一定需要脱离标准文档流,所以我们给它使用绝对定位。

2.利用每个div方块都有相对的坐标值,当鼠标按下移动元素的时候,靠近哪个坐标值,靠近坐标值对应的方块就与当前元素进行位置交换。

3.当前demo,只能存在的bug:元素只能进行交换一次,第二次交换时会发生div被覆盖的结果,不过也提供了另一种思路。

##效果图如下:

代码语言:javascript
复制
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>九宫格</title>
    <style>
        /*CSS样式设置*/
        /*为了方便查看使用通配符去除默认样式,实际开发不建议使用*/
        * {
            margin: 0;
            padding: 0;
        }
        #list {
            width: 390px;
            height: 390px;
            margin: 90px auto 0;
            border-radius: 10px;
            display: flex;
            flex-flow: wrap;
            position: relative;
            /*让div中文字无法被选取,防止因鼠标滑过选取文字而导致鼠标失去焦点*/
            -webkit-touch-callout: none;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
        }
        /*需要给移动的div设置绝对定位,使其脱离标准文档流*/
        div>div {
            width: 130px;
            height: 130px;
            font-size: 50px;
            line-height: 130px;
            border-radius: 8px;
            color: #fff;
            text-align: center;
            font-weight: bold;
            box-sizing: border-box;
            cursor: move;
            position: absolute;
        }
        #d1 {
            top: 0;
            left: 0;
            background-color: #f05b72;
        }
        #d2 {
            background-color: #faa755;
            top: 0;
            left: 130px;
        }
        #d3 {
            top: 0;
            left: 260px;
            background-color: #2585a6;
        }
        #d4 {
            top: 130px;
            left: 0;
            background-color: #50b7c1;
        }
        #d5 {
            top: 130px;
            left: 130px;
            background-color: #69541b;
        }
        #d6 {
            top: 130px;
            left: 260px;
            background-color: #8552a1;
        }
        #d7 {
            top: 260px;
            left: 0;
            background-color: #274d3d;
        }
        #d8 {
            top: 260px;
            left: 130px;
            background-color: #73b9a2;
        }
        #d9 {
            top: 260px;
            left: 260px;
            background-color: #7fb80e;
        }
    </style>
</head>
<body>
<div id="list">
    <div id="d1">1</div>
    <div id="d2">2</div>
    <div id="d3">3</div>
    <div id="d4">4</div>
    <div id="d5">5</div>
    <div id="d6">6</div>
    <div id="d7">7</div>
    <div id="d8">8</div>
    <div id="d9">9</div>
</div>
</body>
<script>
    // 首先获取每个div的ID,声明变量
    var list = document.getElementById("list")
    var d1 = document.getElementById("d1");
    var d2 = document.getElementById("d2");
    var d3 = document.getElementById("d3");
    var d4 = document.getElementById("d4");
    var d5 = document.getElementById("d5");
    var d6 = document.getElementById("d6");
    var d7 = document.getElementById("d7");
    var d8 = document.getElementById("d8");
    var d9 = document.getElementById("d9");
    // 封装函数,方便后续使用
    function box (divname) {
        // 当在divname上点下鼠标发生的事件
        divname.onmousedown = function (env) {
            // 在div移动前先获取每个传入的实参(divname)的位置,留作位置判断失败后返回原位置
            var a1x = divname.offsetLeft;
            var a1y = divname.offsetTop;

            console.log(a1x+"这是")
            console.log(a1y+"这是")
            // 给每个传入的实参(divname)设置层级,不然会被其他div遮挡住
            divname.style.zIndex = "4";
            // env代表事件的状态,设置兼容。
            var env = env || window.event;
            // 获取鼠标当被点击的在div上的位置:
            //     env.clientX(代表当前鼠标距离屏幕左边的位置)。
            //     list.offsetLeft(代表list盒子距离屏幕的左边的位置)。
            //     因为divname设置了绝对定位,所以divname.offsetLeft的参数代表鼠标在div上距离父元素的位置
            //     (env.clientX - list.offsetLeft - divname.offsetLeft)相当于把鼠标当前位置设置为原点
            var divmosue_x = (env.clientX - list.offsetLeft - divname.offsetLeft);
            var divmosue_y = (env.clientY - list.offsetTop - divname.offsetTop);

            // 当在divname上点下鼠标发生并且鼠标在指定的元素中移动
            divname.onmousemove = function (env) {
                var env = env || window.event;
                // 获取鼠标当被点击移动的时候在div上的位置:
                //     env.clientX(代表当前鼠标距离屏幕左边的位置)。
                //     divmosue_x的含义参照上条注释
                //     list.offsetLeft(代表list盒子距离屏幕的左边的位置)。
                //     div_x的含义相当于把鼠标当前坐标点设置为原点
                var div_x = env.clientX - divmosue_x - list.offsetLeft;
                var div_y = env.clientY - divmosue_y - list.offsetTop;
                // 因为divname设置了绝对定位,下面让divname的位置随着鼠标的移动而发生变化
                divname.style.top =  div_y+"px"
                divname.style.left = div_x+"px"
                // 当鼠标松开时的事件,移动的div根据if判断坐标位置,让div符合要求的div交换位置。
                //     并让移动后的双方层级为1,防止元素层级遮挡
                divname.onmouseup = function () {
                    if (div_x > -65 && div_x < 0 && div_y > -65 && div_y < 0) {
                        d1.style.top = a1y + "px";
                        d1.style.left = a1x +"px";
                        divname.style.top = "0px";
                        divname.style.left = "0px"
                        d1.style.zIndex = "1";
                        divname.style.zIndex = "1";
                    }else if (div_x > 65 && div_x < 130 && div_y > -65 && div_y < 0) {
                        d2.style.top = a1y + "px";
                        d2.style.left = a1x +"px";
                        divname.style.top = "0px"
                        divname.style.left = "130px"
                        d2.style.zIndex = "1";
                        divname.style.zIndex = "1";
                    }else if (div_x > 190 && div_x <255  && div_y > -65 && div_y < 0) {
                        d3.style.top = a1y + "px";
                        d3.style.left = a1x +"px";
                        divname.style.top = "0px"
                        divname.style.left = "260px"
                        d3.style.zIndex = "1";
                        divname.style.zIndex = "1";
                    }else if (div_x > -65 && div_x < 0 && div_y > 65 && div_y < 130) {
                        d4.style.top = a1y + "px";
                        d4.style.left = a1x +"px";
                        divname.style.top = "130px"
                        divname.style.left = "0px"
                        d4.style.zIndex = "1";
                        divname.style.zIndex = "1";
                    }else if (div_x > 65 && div_x < 130 && div_y > 65 && div_y < 130) {
                        d5.style.top = a1y + "px";
                        d5.style.left = a1x +"px";
                        divname.style.top = "130px"
                        divname.style.left = "130px"
                        d5.style.zIndex = "1";
                        divname.style.zIndex = "1";
                    }else if (div_x > 190 && div_x <255  && div_y > 65 && div_y < 130) {
                        d6.style.top = a1y + "px";
                        d6.style.left = a1x +"px";
                        divname.style.top = "130px"
                        divname.style.left = "260px"
                    }else if (div_x > -65 && div_x < 0 && div_y > 190 && div_y < 255) {
                        d7.style.top = a1y + "px";
                        d7.style.left = a1x +"px";
                        divname.style.top = "260px"
                        divname.style.left = "0px"
                        d5.style.zIndex = "1";
                        divname.style.zIndex = "1";
                    }else if (div_x > 65 && div_x < 130 && div_y > 190 && div_y < 255) {
                        d8.style.top = a1y + "px";
                        d8.style.left = a1x +"px";
                        divname.style.top = "260px"
                        divname.style.left = "130px"
                        d8.style.zIndex = "1";
                        divname.style.zIndex = "1";
                    }else if (div_x > 190 && div_x <255  && div_y > 190 && div_y < 255) {
                        d9.style.top = a1y + "px";
                        d9.style.left = a1x +"px";
                        divname.style.top = "260px"
                        divname.style.left = "260px"
                        d9.style.zIndex = "1";
                        divname.style.zIndex = "1";
                    }
                    // 如果divname,未符合判断条件,则让它回到原点位置
                    else{
                        console.log("asdsa")
                        console.log(a1x)
                        console.log(a1y)
                        divname.style.top = a1x + "px";
                        divname.style.left = a1y+"px";
                        divname.style.zIndex = "1";
                        divname.onmousemove = null;

                    }
                    divname.onmousemove = null;
                    console.log("松开了");
                }
            }


        }
    }

    box(d1)
    box(d2)
    box(d3)
    box(d4)
    box(d5)
    box(d6)
    box(d7)
    box(d8)
    box(d9)





</script>
</html>

本demo-1参考思路来源于网络,如有侵权,请及时联系删除。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-05-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档