模拟拖拽图片 碰撞检测 DOM 鼠标事件 闭包
<!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 鼠标事件 闭包的更多相关文章
- javascript动画系列第一篇——模拟拖拽
× 目录 [1]原理介绍 [2]代码实现 [3]代码优化[4]拖拽冲突[5]IE兼容 前面的话 从本文开始,介绍javascript动画系列.javascript本身是具有原生拖放功能的,但是由于兼容 ...
- JavaScript动画-模拟拖拽
模拟拖拽的原理: x1等于div.offsetLeft y1等于div.offsetTop x2等于ev.clientX(ev表示event事件) y2等于ev.clientY 当我们在方块上按下鼠标 ...
- 在viewPager中双指缩放图片,双击缩放图片,单指拖拽图片
我们就把这个问题叫做图片查看器吧,它的主要功能有: (项目地址:https://github.com/TZHANHONG/ImageViewer/releases/tag/1.0,里面的MyImage ...
- 基于html5可拖拽图片循环滚动切换
分享一款基于html5可拖拽图片循环滚动切换.这是一款支持手机端拖拽切换的网站图片循环滚动特效.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div id="s ...
- android 拖拽图片&拖动浮动按钮到处跑
来自老外: 拖拽图片效果 方法一: 布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLa ...
- 鼠标拖拽定位和DOM各种尺寸详解
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- javascript--鼠标拖拽窗口案例(鼠标按下,在鼠标移动过程中,盒子跟着一起移动,鼠标松开,盒子停止移动)
界面如图所示: 要求:在“信息注册”栏,按下鼠标,然后鼠标在页面移动,在鼠标移动过程中,该窗口跟着鼠标移动,当鼠标松开的时候,窗口停止移动.点击“关闭”,该窗口隐藏. 实现思路: 1.页面结构分析:一 ...
- 拖拽图片到另一个div里
HTML代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- js 禁止右击保存图片,禁止拖拽图片
禁止鼠标右键保存图片 <img src="" oncontextmenu="return false;"> 禁止鼠标拖动图片 <img src ...
随机推荐
- 28 Data Race Detector 数据种类探测器:数据种类探测器手册
Data Race Detector 数据种类探测器:数据种类探测器手册 Introduction Usage Report Format Options Excluding Tests How To ...
- python dict交换key value值
方法一: 使用dict.items()方式 dict_ori = {'A':1, 'B':2, 'C':3} dict_new = {value:key for key,value in dict_o ...
- java基础28 单例集合Collection下的List和Set集合
单例集合体系: ---------| collection 单例集合的根接口--------------| List 如果实现了list接口的集合类,具备的特点:有序,可重复 注:集合 ...
- Kafka压力测试(自带测试脚本)(单机版)
一.测试目的 本次性能测试在正式环境下单台服务器上Kafka处理MQ消息能力进行压力测试.测试包括对Kafka写入MQ消息和消费MQ消息进行压力测试,根据10w.100w和1000w级别的消息处理结果 ...
- 20155225 实验一《Java开发环境的熟悉》实验报告
20155225 实验一<Java开发环境的熟悉>实验报告 一.命令行下Java程序的开发 按照老师提供的步骤,运行程序如下: 二.IDEA下Java程序开发.调试 设置条件断点如下: 三 ...
- 【LOJ】#2447. 「NOI2011」兔兔与蛋蛋的游戏
题解 对于75分来说,操作肯定不会成环,可以暴搜 看成空格在移动,空格移动到原来的位置肯定经历了偶数个格子,但是操作的人是两个不同的人,所以肯定不会成环 对于满分做法,要找到一种更好的方式判先手是否会 ...
- 包装印刷行业裕同集团&易普优APS项目顺利验收!
裕同集团&易普优APS项目于2017年7月启动,2018年1月上线,2018年5月初项目顺利验收!历时十个月,龙岗作为裕同集团APS的先锋试点项目,同时也是业务最复杂的分公司,双方联合团队紧密 ...
- 浅谈jvm
1 .说起jvm,很多人感觉jvm离我们开发实际很远.但是,我们开发缺每时每刻都离不开jvm. a: java源码 编译后成.class字节码文件, b:根据classpath找到这个字节码文件, c ...
- 003 Ajax中传输格式为XML
一: 1.优缺点 二:大纲 1.结构设计 三:程序 1.xml <?xml version="1.0" encoding="utf-8"?> < ...
- 成为IT经理必备的十大能力 不只是技术!
对于一个IT从业者,让你谋得工作的也许是技术能力,但有助于提升职业生涯的却是软技能.步步高升的人都是那些发表文章.在会议上积极发言以及关注客户的员工(程序员).与此同时,通常情况下,企业CIO或多或少 ...