使用原生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-1的BUG要处理掉,把,要把移动的 标签放到结构的最后,然后循环的时候将他排除掉,不然每次距离最近的都是它本身)。 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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
华山资源网 Design By www.eoogi.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
华山资源网 Design By www.eoogi.com
暂无评论...
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
2024年12月22日
2024年12月22日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]