<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>图片拖拽</title>
<style type="text/css">
body,ul{
margin:0px;
padding:0px;
}
.box{
position:relative;
width:380px;
height:380px;
margin:100px auto;
border:1px solid black;
}
.box ul li{
margin:20px 0 0 20px;
width:100px;
height:100px;
list-style:none;
float:left;
}
.box ul li img{
display:inline-block;
}
</style>
</head>
<body>
<div class="box">
<ul class="imgWrapper">
<li><img src="1.jpg" alt="" width="100px" height="100px" /></li>
<li><img src="2.jpg" alt="" width="100px" height="100px" /></li>
<li><img src="3.jpg" alt="" width="100px" height="100px" /></li>
<li><img src="4.jpg" alt="" width="100px" height="100px" /></li>
<li><img src="5.jpg" alt="" width="100px" height="100px" /></li>
<li><img src="6.jpg" alt="" width="100px" height="100px" /></li>
<li><img src="7.jpg" alt="" width="100px" height="100px" /></li>
<li><img src="8.jpg" alt="" width="100px" height="100px" /></li>
<li><img src="9.jpg" alt="" width="100px" height="100px" /></li>
</ul>
</div>

<script type="text/javascript">

//全局变量一定要少定义
//容易出错 还占内存

/*图标拖拽
1.如果想让图标移动 那就得把浮动布局改为浮动布局
1.1
操作系统和浏览器是多线程(伪多线程)
是在非常短的时间内执行单个线程比如1um
比如一秒内就可以完成多个单线程
而JS是单线程
当四个任务让浏览器执行的时候
因为是单线程 谁执行快返回谁
所以 写的代码有的时候和返回的而结果不一样

2.当鼠标点住一张图片的时候 图片可以拖动(鼠标移动)
2.1事件代理 点击事件 //有点行不通
2.1 onmousedown onmousemove onmouseup
循环给每个li元素加上
2.2 记录点击的那个位置 两次鼠标位置相减 加上自身偏移量 都会改变left top值
让图片跟着鼠标走

3.在拖动图片的时候碰撞检测

3.1 计算与周围的图标的距离 距离最短的那个图片添加border
3.2如果没有检测到 则松开鼠标的时候 图片回到原始位置
3.3当松开鼠标的时候 图片位置平滑交换
3.4
*/

//获取元素的时候 不是数组 要转化为数组 或者 把所需要的内容添加到自定义数组中
var liList=document.querySelectorAll(".box ul li ");//伪数组
var imgWrapper=document.querySelector(".imgWrapper");
var nearElement=null;
var arr=Array.prototype.slice.call(liList);
var liPos=[];
var sign=[];
var num=1;
var control=false;

function deleteBorder(arr){

for(var i=0,item;item=arr[i++];){

arr[i-1].style.border="";

}

}

function pos(){

/*设置比获取速度要快
如果想让设置之在获取之后就要让他的执行速度变慢
可以用定时器 定时器 要注意闭包作用域的问题
函数立执行
*/

for( var j=0,len=arr.length;j<len;j++){

liPos.push([arr[j].offsetLeft,arr[j].offsetTop]);
//函数自执行
(function(n){
setTimeout(function(){
arr[n].style.position="absolute"; //把浮动改成定位
arr[n].style.left=liPos[n][0]+"px"; //重新设置位置
arr[n].style.top=liPos[n][1]+"px";
arr[n].style.margin="0";//margin设置为0 不然会有两个margin距离
},0);
})(j);

}
}
pos();

//mousedown mouseover mouseup
//给每个li添加事件
for(var i=0,item;item=arr[i++];){
//给元素添加index属性
arr[i-1].index=i-1;
drag(arr[i-1]);

}
//拖拽
function drag(obj){

obj.onmousedown=function(e){
e.preventDefault();
var oldX=e.offsetX;
var oldY=e.offsetY;
++num;
obj.style.zIndex=num;

obj.onmousemove=function(e){

var newX=e.offsetX;
var newY=e.offsetY;

obj.style.left=(newX-oldX+obj.offsetLeft)+"px";
obj.style.top=(newY-oldY+obj.offsetTop)+"px";
for(var i=0,len=arr.length;i<len;i++){
if(!impact(obj,arr[i])&&obj!=arr[i]){
if(!impact(obj,arr[i])){

//记录下碰撞成功的元素
sign.push(arr[i]);
}
else{
//没有碰撞的话元素边框消失
arr[i].style.border="";
}

}
}

//在碰撞中的元素中找到最短的那个设置边框
if(!(sign&&sign.length==0)){// 当sign数组里面没有元素的时候不执行
nearElement=nearDistance(obj,sign);
nearElement.style.border="1px solid red"
}

}

}
//鼠标抬起 平滑交换位置 动画
obj.onmouseup=function(){
obj.onmousemove=null;

if(!(sign&&sign.length==0)){

move(obj,[liPos[obj.index][0],liPos[obj.index][1]],[liPos[nearElement.index][0],liPos[nearElement.index][1]]);
move(nearElement,[liPos[nearElement.index][0],liPos[nearElement.index][1]],[liPos[obj.index][0],liPos[obj.index][1]]);

deleteBorder(arr);
//交换完之后 index 交换
var index=nearElement.index;
nearElement.index=obj.index;
obj.index=index;
//全局变量一定要注意
sign=[];

}
else{
obj.style.left=liPos[obj.index][0]+"px";
obj.style.top=liPos[obj.index][1]+"px";
}
}

}

//碰撞检测
function impact(obj1,obj2){

var L1=obj1.offsetLeft;
var T1=obj1.offsetTop;
var R1=L1+obj1.offsetWidth;
var B1=T1+obj1.offsetHeight;

var L2=obj2.offsetLeft;
var T2=obj2.offsetTop;
var R2=L2+obj2.offsetWidth;
var B2=T2+obj2.offsetHeight;

if(L1>R2||R1<L2||T1>B2||B1<T2){//满足其中任和一个 都不可能碰撞

return true;

}
else{
return false;
}

}

//判断最短距离
function nearDistance(obj,arr){
//第一个数组里面保存的事li元素 第二个保存的是斜边长度
//根据对应的斜边长度找到对应的元素
var value=[[],[]];
for(var i=0,len=arr.length;i<len;i++){
//勾股定理

var a=arr[i].offsetLeft-obj.offsetLeft;
var b=arr[i].offsetTop-obj.offsetTop;
//计算最短斜边
value[0].push(arr[i]);
value[1].push(Math.sqrt(a*a+b*b));
}

//返回最小斜边对应的那个li元素 设置边框之前其他的边框清除 然后设置碰撞最短元素边框
deleteBorder(arr);
//这段代码可读性不太好
return value[0][value[1].indexOf(Math.min.apply(Math,value[1]))];
}

//事件运动函数
function move(obj,current,target){
//X,Y轴都会变化

//时间运动公式 s=t*S/T
var T=500;
var t=new Date();
var Sx=target[0]-current[0];
var Sy=target[1]-current[1];
var timer=null;
var stepX=0,stepY=0;
var changeTime=0;
//var currentX=0,currentY=0;
timer=setInterval(function(){
changeTime=new Date()-t;
//currentX=obj.offsetLeft;
//currentY=obj.offsetTop;
if(changeTime/T>=1){
clearInterval(timer);
obj.style.left=target[0]+"px";
obj.style.top=target[1]+"px";
}
else{

stepX=parseInt(changeTime*Sx/T);
stepY=parseInt(changeTime*Sy/T);
obj.style.left=current[0]+stepX+"px";
obj.style.top=current[1]+stepY+"px";
}

},1000/60);

}

</script>
</body>
</html>

模拟拖拽图片 碰撞检测 DOM 鼠标事件 闭包的更多相关文章

  1. javascript动画系列第一篇——模拟拖拽

    × 目录 [1]原理介绍 [2]代码实现 [3]代码优化[4]拖拽冲突[5]IE兼容 前面的话 从本文开始,介绍javascript动画系列.javascript本身是具有原生拖放功能的,但是由于兼容 ...

  2. JavaScript动画-模拟拖拽

    模拟拖拽的原理: x1等于div.offsetLeft y1等于div.offsetTop x2等于ev.clientX(ev表示event事件) y2等于ev.clientY 当我们在方块上按下鼠标 ...

  3. 在viewPager中双指缩放图片,双击缩放图片,单指拖拽图片

    我们就把这个问题叫做图片查看器吧,它的主要功能有: (项目地址:https://github.com/TZHANHONG/ImageViewer/releases/tag/1.0,里面的MyImage ...

  4. 基于html5可拖拽图片循环滚动切换

    分享一款基于html5可拖拽图片循环滚动切换.这是一款支持手机端拖拽切换的网站图片循环滚动特效.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div id="s ...

  5. android 拖拽图片&拖动浮动按钮到处跑

    来自老外: 拖拽图片效果 方法一: 布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLa ...

  6. 鼠标拖拽定位和DOM各种尺寸详解

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. javascript--鼠标拖拽窗口案例(鼠标按下,在鼠标移动过程中,盒子跟着一起移动,鼠标松开,盒子停止移动)

    界面如图所示: 要求:在“信息注册”栏,按下鼠标,然后鼠标在页面移动,在鼠标移动过程中,该窗口跟着鼠标移动,当鼠标松开的时候,窗口停止移动.点击“关闭”,该窗口隐藏. 实现思路: 1.页面结构分析:一 ...

  8. 拖拽图片到另一个div里

    HTML代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  9. js 禁止右击保存图片,禁止拖拽图片

    禁止鼠标右键保存图片 <img src="" oncontextmenu="return false;"> 禁止鼠标拖动图片 <img src ...

随机推荐

  1. 33 Introducing the Go Race Detector

    Introducing the Go Race Detector 26 June 2013 Introduction Race conditions are among the most insidi ...

  2. Failed to create the Java Virtual Machine

    启动Zend Studio时出现Failed to create the Java VIrtual Machine 解决办法如下.打开安装目录下的ZendStudio.ini配置文件,作如下修改: 说 ...

  3. hdu 5112 (2014北京现场赛 A题)

    给出某个时刻对应的速度 求出相邻时刻的平均速度 输出最大值 Sample Input23 // n2 2 //t v1 13 430 31 52 0 Sample OutputCase #1: 2.0 ...

  4. 书接前文,用多进程模式实现fibonnachi并发计算

    #coding: utf-8 import logging import os import random import sys import time import re # import requ ...

  5. tomcat下程序包的安装与部署

    还没亲自在服务器进行部署,但是参考了公司文档,等自己安装部署的时候,再将文档补充完整. 1.初始化数据库 2.修改war包的数据 主要包括的一些配置是数据库的连接配置. 3.将包发布 这个步骤下有几个 ...

  6. IOS成长之路-Xcode cannot run using the selected device. 解决办法

    PROJECT --> Info --> Deployment Target --> IOS Deployment Target  里面的值 要设置为  <=真机系统版本 TA ...

  7. SpringSecurity3基础篇

    Spring Security 是一种基于Spring AOP 和Servlet过滤器的安全框架,它提供了全面的安全性解决方案,同时在Web请求级和方法调用级处理身份确认和授权.在Spring Fra ...

  8. LINUX 下挂载 exfat 格式 u 盘或移动硬盘

    apt-get update apt-get install exfat-utils

  9. [js]正则篇

    一.正则基本概念 1.一种规则.模式.文本处理工具 2.强大的字符串匹配工具 3.在js中常与字符串函数配合使用 二.js正则写法 正则在js中以正则对象存在: (1)var re=new RegEx ...

  10. 大数据技术之_16_Scala学习_04_函数式编程-基础+面向对象编程-基础

    第五章 函数式编程-基础5.1 函数式编程内容说明5.1.1 函数式编程内容5.1.2 函数式编程授课顺序5.2 函数式编程介绍5.2.1 几个概念的说明5.2.2 方法.函数.函数式编程和面向对象编 ...