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

 

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

Demo-1整体思路:

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

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

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

##效果图如下:

网页源代码:

<!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被覆盖的结果,不过也提供了另一种思路。

##效果图如下:

<!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参考思路来源于网络,如有侵权,请及时联系删除。

(Demo分享)利用JavaScript(JS)实现一个九宫格拖拽功能的更多相关文章

  1. Javascript写的一个可拖拽排序的列表

    自己常试写了一个可拖拽进行自定义排序的列表,可能写的不太好,欢迎提供意见. 我的思路是将列表中的所有项都放进一个包裹层,将该包裹层设为相对定位,每当点击一个项时,将该项脱离文档并克隆一份重新添加到文档 ...

  2. 通过 JS 实现简单的拖拽功能并且可以在特定元素上禁止拖拽

    前言 关于讲解 JS 的拖拽功能的文章数不胜数,我确实没有必要大费周章再写一篇重复的文章来吸引眼球.本文的重点是讲解如何在某些特定的元素上禁止拖拽.这是我在编写插件时遇到的问题,其实很多插件的拖拽功能 ...

  3. (Demo分享)利用JavaScript(JS)做一个可输入分钟的倒计时钟功能

    利用JavaScript(JS)实现一个可输入分钟的倒计时钟功能本文章为 Tz张无忌 原创文章,转载请注明来源,谢谢合作! 网络各种利用JavaScript做倒计时的Demo对新手很不友好,这里我亲手 ...

  4. JS利用 Sea.js 实现模块化:拖拽、缩放及范围限制

    知识点总结: Sea.js的使用:define.export.seajs.use.require等方法:   参考:http://seajs.org/docs/ Sea.js与require.js的区 ...

  5. d3.js v4曲线图的拖拽功能实现Zoom

    zoom缩放案例 源码:https://github.com/HK-Kevin/d...:demo:https://hk-kevin.github.io/d3...: 原理:通过zoom事件来重新绘制 ...

  6. 原生js实现一个简单的倒计时功能

    大家好,我是云中君!欢迎大家来观看我的博客 之前那,在群里看到很多人问,关于电商网站中的倒计时功能怎么实现,很多人说在网上找了很多插件,但是不是很会用,所以今天就在这里分享一下我封装的一个小的倒计时功 ...

  7. 利用原生JS实现类似浏览器查找高亮功能(转载)

    利用原生JS实现类似浏览器查找高亮功能 在完成 Navify 时,增加一个类似浏览器ctrl+f查找并该高亮的功能,在此进行一点总结: 需求 在.content中有许多.box,需要在.box中找出搜 ...

  8. JS事件 编程练习-自制计算器 使用JS完成一个简单的计算器功能。实现2个输入框中输入整数后,点击第三个输入框能给出2个整数的加减乘除。

    编程练习 使用JS完成一个简单的计算器功能.实现2个输入框中输入整数后,点击第三个输入框能给出2个整数的加减乘除. 提示:获取元素的值设置和获取方法为:例:赋值:document.getElement ...

  9. dropzonejs中文翻译手册 DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库.

    http://wxb.github.io/dropzonejs.com.zh-CN/dropzonezh-CN/ 由于项目需要,完成一个web的图片拖拽上传,也就顺便学习和了解了一下前端的比较新的技术 ...

随机推荐

  1. 外部进程嵌入到Qt进程界面(使用QWindow::fromWinId)

    有时候需要做框架集成的东西,需要把其他客户端像组件一样集成到一个客户端中,类似于一个软件集成的平台客户端,统一用一个中心管理的客户端做类似于控制面板一样的东西去调用不同的软件.此时就必须相应不同的点击 ...

  2. LaTex 加粗(加黑)的方式

    1. 基本 LaTeX技巧458:关于LaTeX数学字体加粗 $\mathbf $,会变为粗体,但也导致数学字母斜体形式的丢失: 使用 amsmath package 的 \boldmath 命令: ...

  3. phpstorm 删除空行

    思路: 用正则把所有空行找到,然后一键全部替换. 步骤:首先把 Regex 打上勾ctrl+f 搜索框就填写正则规则:^\nctrl+r 匹配到所有空行之后,点击[Replace all]即可

  4. Atitit.故障排除系列---php 计划网站数据库错误排除过程

    Atitit.故障排除系列---php 计划网站数据库错误排除过程 Php页面报告的错误不能定位到myusql的db配置上...字说是db conn err Mysql 接入错误...大概查看哈能不能 ...

  5. Linux性能测试 ss命令

    ss即socket state,也就是说,是可以查看系统中socket的状态的.我们可以用netstat,但为什么还要用ss这个工具呢,当然ss也是有好处的.当我们打开的socket数量很多时,net ...

  6. ASP.NET Core 配置 MVC - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 配置 MVC - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 配置 MVC 前面几章节中,我们都是基于 ASP.NET 空项目 ...

  7. .net reactor 学习系列(三)---.net reactor代码自动操作相关保护功能

    原文:.net reactor 学习系列(三)---.net reactor代码自动操作相关保护功能         接上篇,上篇已经学习了界面的各种功能以及各种配置,这篇准备学习下代码控制许可证. ...

  8. crawler_正则表达式零宽断言

    在使用正则表达式时,有时我们需要捕获的内容前后必须是特定内容,但又不捕获这些特定内容的时候,零宽断言就起到作用了. (?=exp):零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp. ...

  9. BZOJ 3329 Xorequ 数字DP+矩阵乘法

    标题效果:特定n,乞讨[1,n]内[1,2^n]差多少x满足x^3x=2x x^3x=2x相当于x^2x = 3x 和3x=x+2x 和2x=x<<1 因此x满足条件IFFx&(x ...

  10. linux没有 conio.h解决的方式

    conio.h不是C标准库中的头文件,在ISO和POSIX标准中均未定义. conio是Console Input/Output(控制台输入输出)的简写,当中定义了通过控制台进行数据输入和数据输出的函 ...