zl程序教程

您现在的位置是:首页 >  其他

当前栏目

模拟拖拽图片 碰撞检测 DOM 鼠标事件 闭包详解编程语言

事件模拟编程语言 详解 图片 鼠标 dom 闭包
2023-06-13 09:20:36 时间

!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 > ul > 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 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 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 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

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/12286.html

cjava