在开发某网站系统时,经常会遇到什么什么掠影,什么什么产品等一大堆图片的逐个排列,为了交互效果更优美,在此实现所有图片可拖拽,并且在拖拽过程中与被碰撞的图片交换位置;如果没有碰撞的图片则要回归原位置。
效果:
源码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>图片墙</title>
<script src="../js/jquery-1.11.1.min.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#ul1 {
width: 1000px;
margin: 0 auto;
list-style: none;
position: relative;
}
#ul1 li{
width: 200px;
height: 150px;
float:left;
margin: 10px;
}
img{
width: 200px;
height: 150px;
}
.active{
border: dashed 1px red;
}
</style>
</head>
<body>
<ul id='ul1'>
<li>
<img src="img/1.jpg" />
</li>
<li>
<img src="img/2.jpg" />
</li>
<li>
<img src="img/3.jpg" />
</li>
<li>
<img src="img/4.jpg" />
</li>
<li>
<img src="img/5.jpg" />
</li>
<li>
<img src="img/6.jpg" />
</li>
<li>
<img src="img/7.jpg" />
</li>
<li>
<img src="img/8.jpg" />
</li>
<li>
<img src="img/9.jpg" />
</li>
<li>
<img src="img/10.jpg" />
</li>
<li>
<img src="img/11.jpg" />
</li>
<li>
<img src="img/12.jpg" />
</li>
</ul>
<script type="text/javascript" charset="utf-8">
var oUl=document.getElementById("ul1"),
aLi=oUl.getElementsByTagName('li'),
aPos=[],
iMinIndex=2;
//布局转换,先记忆所有Li的位置,然后根据这些位置转换为绝对定位
for (var i=0,l=aLi.length;i<l;i++) {
aPos.push({left:aLi[i].offsetLeft,top:aLi[i].offsetTop});
}
for (var i=0,l=aLi.length;i<l;i++) {
aLi[i].style.position='absolute';
aLi[i].style.left=aPos[i].left+'px';
aLi[i].style.top=aPos[i].top+'px';
aLi[i].style.margin=0;
aLi[i].index=i;
}
//设置每一个Li可拖拽
for (var i=0,l=aLi.length;i<l;i++) {
setDrag(aLi[i]);
}
function setDrag(obj){
obj.οnmοusedοwn=function(e){
obj.style.zIndex=iMinIndex++;
e=e||event;
var disX=e.clientX-obj.offsetLeft,
disY=e.clientY-obj.offsetTop;
if(obj.setCapture){
obj.οnmοusemοve=fnMove;
obj.οnmοuseup=fnUp;
obj.setCapture();
}else{
document.οnmοusemοve=fnMove;
document.οnmοuseup=fnUp;
}
return false;
function fnMove(e){
e=e||event;
obj.style.left=e.clientX-disX+(document.documentElement.scrollLeft||document.body.scrollLeft)+'px';
obj.style.top=e.clientY-disY+(document.documentElement.scrollTop||document.body.scrollTop)+'px';
//移动物体时检查碰撞并找到碰撞中最近的那个物体
for (var i=0,l=aLi.length;i<l;i++){
aLi[i].className='';
}
var oNearest=findNearest(obj);
if(oNearest){
oNearest.className='active';
}
}
function fnUp(){
this.οnmοusemοve=null;
this.οnmοuseup=null;
if(obj.releaseCapture){
obj.releaseCapture();
}
//鼠标抬起,有碰撞的交换位置否则回到原位置
var oNearest=findNearest(obj);
if(oNearest){
//去除碰撞的物体样式
oNearest.className='';
//防止两物体在其它物体下面钻来钻去
oNearest.style.zIndex=iMinIndex++;
obj.style.zIndex=iMinIndex++;
//两物体交换位置
$(obj).animate({
left:aPos[oNearest.index].left,
top:aPos[oNearest.index].top
},'fast');
$(oNearest).animate({
left:aPos[obj.index].left,
top:aPos[obj.index].top
},'fast');
//两物体的位置索引交换
var temp=obj.index;
obj.index=oNearest.index;
oNearest.index=temp;
}else{
$(obj).animate({
left:aPos[obj.index].left,
top:aPos[obj.index].top
},'fast');
}
}
};
}
//碰撞检测
function cdTest(o1,o2){
var l1=o1.offsetLeft,
r1=l1+o1.offsetWidth,
t1=o1.offsetTop,
b1=t1+o1.offsetHeight;
l2=o2.offsetLeft,
r2=l2+o2.offsetWidth,
t2=o2.offsetTop,
b2=t2+o2.offsetHeight;
if(r1<l2||b1<t2||l1>r2||t1>b2){
return false;
}else{
return true;
}
}
//计算两个物体之间的距离
function getDis(o1,o2){
var a=o1.offsetLeft-o2.offsetLeft,
b=o1.offsetTop-o2.offsetTop;
return Math.sqrt(a*a+b*b);
}
//找到最近的碰撞物体
function findNearest(obj){
var iMinDistance=Number.MAX_VALUE,
iIndex=-1;
for (var i=0,l=aLi.length;i<l;i++){
if(aLi[i]==obj){
continue;
}
if(cdTest(obj,aLi[i])){
var dis=getDis(obj,aLi[i]);
if(dis<iMinDistance){
iMinDistance=dis;
iIndex=i;
}
}
}
if(iIndex==-1){
return null;
}else{
return aLi[iIndex];
}
}
</script>
</body>
</html>
所有图片均来自网络,如有版权问题,请告知并删除。