原生js写九宫格拖拽换位

使用原生JS写出一个九宫格,实现九个格子可以拖拽换位的效果

效果演示

在这里插入图片描述

具体思路分析和代码:

图解1:
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        思路梳理:
            1,样式设置:在样式里最好使用定位来布局,不然以后拖拽代码会麻烦点儿。
            			(这里没有设置父容器的具体位置,如果设置了父容器的具体位置,则在移动
            			时top和left的值需要根据情况计算位置)
            2,父容器盒子里的内容最好使用js代码来生成,方便使用和添加样式
                2-1:(循环生成子元素)
                    我们子元素使用的定位布局,不难发现:每行的top值一样,每列的left值一样,因此循环生
                    成子元素我们可以使用3*3的循环嵌套来写,这样就可以讲每行的样式设置了。
                2-2:(给循环生成的标签添加随机颜色和文字)
                    随机颜色我是用的时rgb()来实现的,文字可以使用ASCII码来生成,也可以使用字符串拼接
                    来生成,我这里使用ASCII码生成。
                PS:这样我们的基本样式就设置完毕了,接下来就是设置拖拽的事件
            3,给每一个元素添加事件,这里我们需要三个事件: onmousedown - onmousemove - onmouseup
                3-1:(首先是按下事件  onmousedown)
                    当我们在对应子元素按下时,我们要获取鼠标到按下目标边框线内的距离,并且克隆这个元素,
                    将这个元素扔到父容器里面充当占位,(这里注意,克隆的这个节点在HTML结构里是放到最后
                    的,如果不处理后面会出BUG!!!)。
                3-2:(然后处理移动事件  onmousemove)
                    在按下子元素块儿并且移动时,我们要给目标设置他的top和left值,来实现跟随移动,所以
                    我们需要获取鼠标到可视窗口的距离,目标的top和left值 = 鼠标到可视窗口的距离 - 鼠标
                    到目标边缘的距离(这里无边框,如果有需要额外减去边框宽度)。
                    PS:    
                        这里存在一个BUG!!!!在拖拽时,存在一个默认事件--选中文字,当你松开之后,目
                        标还会跟着走,就算你关闭了onmousemove这个事件。所以这里需要阻止一下默认事件。
                3-3:(最后处理抬起事件  onmouseup)这里也是最重要的一步!!!!
                    核心思想:
                            当鼠标抬起时,我们要计算当前移动目标的中心点和每一个子元素中心点的距离,
                            哪一个离得最近,和哪个交换位置(注意,这里存在一个BUG,这里的BUG就是
                             3-1 里提到的BUG,需要提前处理)。
                    具体过程:
                        3-3-1:
                            首先我们要进行循环,计算拖拽目标的中心点与每一个子元素的中心点的距离,具体
                            参照  图解1 。  (拖拽目标距离可视窗口的左边距 - 子元素距离可视窗口的左边
                            距)平方  +  (拖拽目标距离可视窗口的上边距 - 子元素距离可视窗口的上边距)
                            平方。最后在开方,得到中心点的距离(注意3-1BUG要处理掉,把,要把移动的
                            标签放到结构的最后,然后循环的时候将他排除掉,不然每次距离最近的都是它本身)。
                        3-3-2:
                            我们循环会得到我们想要的每一个距离,然后将这些距离放到一个数组里,并且再定
                            义一个数组备份一下,方便对照具体是哪个标签。
                            将其中一个数组进行排序,然后再备份数组中查一下最小的值在备份数组中的索引下
                            标,这个索引下标也就是对应的子元素了。
                        3-3-3:
                            然后将距离最近的子元素的  left和top值给  目标元素
                            然后将克隆的标签的  left和top值给  距离最近的子元素
                            最后在将克隆的标签移除掉

                            这里还是会有一个BUG!!!如果不在标签上按 直接抬起鼠标的话,会报错,这是因
                            为直接执行了onmouseup事件,所以需要移除掉onmouseup事件   
     -->
     <style>
        *{margin: 0;padding: 0;}
        .father{position: relative;}
        .father div{position: absolute;width: 100px;height: 100px;border-radius: 10px;text-align: center;line-height: 100px;font-size: 30px;cursor: pointer;}
     </style>
</head>
<body>
    <div class="father"></div>
    <script>
        // 3*3 循环生成子元素div,并给他们设置定位值
        // 设定固定的margin值
        var mT = 15;
        var mL = 15;
        var asc = 65;//ASCII码值
        var oFather = document.querySelector('.father');
        for(var i = 0; i < 3; i++){
            for(var j = 0; j < 3; j++){
                var oDiv = document.createElement('div');//创建子元素
                oFather.appendChild(oDiv);
                oDiv.style.left = j * (oDiv.offsetWidth + mL) +'px';
                oDiv.style.top = i * (oDiv.offsetHeight + mT) +'px';
                // 随机颜色设置
                oDiv.style.background = 'rgb('+parseInt(Math.random()*256) + "," +parseInt(Math.random()*256) + ","+parseInt(Math.random()*256)+')';
                // 加上字母
                oDiv.innerText = String.fromCharCode(asc++);
            }
        }
        // 为了方便理解,将事件写到了外面,这里可以生成标签循环内部
        /* var oItem = document.querySelectorAll('.father>div');
        这种方式获取的是静态集合,只会获取到初次页面加载的内容,用这种办法获取子元素会出BUG */
        var oItem = oFather.children;
        for(var k = 0 ;k<oItem.length; k++){
            oItem[k].onmousedown = function(e){
                var evt = e || event;
                // 获取鼠标到目标边框内的距离
                var x = e.offsetX;
                var y = e.offsetY;
                var tagNode = this;
                // 克隆目标标签
                var cloneNode = tagNode.cloneNode();
                cloneNode.style.border = '1px dashed #fff';
                oFather.appendChild(cloneNode);
                tagNode.style.zIndex = 1;
                // 在思路里提到过,这里存在一个BUG需要将克隆的和被拖拽换位置
                oFather.replaceChild(cloneNode, tagNode);
                oFather.appendChild(tagNode);
                document.onmousemove = function(e){
                    var evt = e || event ; 
                    var l = evt.clientX - x;
                    var t = evt.clientY - y;
                    tagNode.style.left = l + 'px';
                    tagNode.style.top = t + 'px';
                    // 阻止默认事件,防止bug
                    return false;
                }
                document.onmouseup = function(){
                    // 抬起鼠标后,要判断离那个最近,然后交换
                    
                    var oldArr = [];
                    var newArr = [];
                    for(var l = 0; l<oItem.length - 1;l++){
                        var disX = tagNode.offsetLeft - oItem[l].offsetLeft;
                        var disY = tagNode.offsetTop - oItem[l].offsetTop;
                        // 勾股定理
                        var dis = Math.sqrt( Math.pow(disX,2) + Math.pow(disY,2) );
                        oldArr.push(dis);
                        newArr.push(dis);
                    }
                    // 将oldArr从小到大排序
                    oldArr.sort(function(a,b){return a-b});
                    var minIndex = newArr.indexOf(oldArr[0]);

                    console.log('oldArr' , oldArr, 'newArr' ,newArr);

                    // 将距离最近的元素的定位给移动的目标
                    tagNode.style.top = oItem[minIndex].style.top;
                    tagNode.style.left = oItem[minIndex].style.left;
                    // 把克隆的定位给距离最近的
                    oItem[minIndex].style.top = cloneNode.style.top;
                    oItem[minIndex].style.left = cloneNode.style.left;

                    //把克隆节点移除
                    oFather.removeChild(cloneNode);

                    document.onmousemove = null;
                    document.onmouseup = null;
                }
                return false;
            }
        }
    </script>
</body>
</html>
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
原生 JavaScript 实现三级分销小 Demo 的主要步骤如下: 1. 创建三个用户: 1) 顶级用户:拥有最高级别的分销权力。 2) 一级用户:由顶级用户推广而来,拥有中级分销权力。 3) 二级用户:由一级用户推广而来,拥有最低级别的分销权力。 2. 定义用户类,并设置三个属性:姓名、级别、推广收益。 ```javascript class User { constructor(name, level) { this.name = name; this.level = level; this.profit = 0; } } ``` 3. 创建用户实例,并设置级别和姓名: ```javascript const topUser = new User("顶级用户", "顶级"); const firstLevelUser = new User("一级用户", "一级"); const secondLevelUser = new User("二级用户", "二级"); ``` 4. 实现用户推广的方法,即通过推广链接注册用户,上级用户获得相应的推广收益: ```javascript function promoteUp(user, invitee) { if (user.level === "顶级") { invitee.profit += 100; // 顶级用户推广新用户获得100元推广收益 } else if (user.level === "一级") { invitee.profit += 50; // 一级用户推广新用户获得50元推广收益 } else if (user.level === "二级") { invitee.profit += 30; // 二级用户推广新用户获得30元推广收益 } } ``` 5. 测试推广的过程: ```javascript promoteUp(topUser, firstLevelUser); // 顶级用户推广一级用户 promoteUp(firstLevelUser, secondLevelUser); // 一级用户推广二级用户 ``` 6. 输出用户的推广收益: ```javascript console.log(topUser.profit); // 输出 100 console.log(firstLevelUser.profit); // 输出 50 console.log(secondLevelUser.profit); // 输出 30 ``` 这就是一个简单的原生 JavaScript 实现的三级分销小 Demo。通过不同的级别和推广链接,上级用户可以获得相应的推广收益。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值