第十一周第二天笔记之照片墙实例
2018-10-08 本文已影响0人
果木山
1 照片墙实例
- 需求:图片可拖拽,当拖拽的图片与其他图片重合时,当鼠标抬起事件发生时,与重合最多的进行位置互换,如果没有重合图片就回到原来位置,当点击图片拖拽时,图片的边框为黄色,在拖拽过程中,如重合最多的图片的边框也变成黄色,当鼠标抬起后,两张图片进行位置互换,互换完成后边框恢复原来颜色;
- 思路:
- 页面布局,浮动布局,添加margin间距;
- 如果需要拖拽,图片的布局必须是定位布局,所以需要将浮动布局转化为定位布局;
- 遍历图片,添加拖拽功能,利用在拖拽中的接口来增加功能,进行绑定执行;
- 在mousedown事件中设置的接口行为是myDragDown,给其绑定行为方法,当鼠标按下时,将该图片的层级提高,浮在所有图片之上;
- 在mousemove事件中设置的接口行为是myDragMove,给其绑定行为方法,当鼠标移动时,判断跟哪个图片进行碰撞,如果碰撞了就放入ary数组中,然后对数组进行一系列的操作;
- 通过公式计算出斜边的距离,赋值在图片的自定义属性上,距离越短,证明重合越多,所以需要对ary数组中的每一项身上的自定义属性值进行排序,然后取最小的,对其进行操作;将其边框变为黄色;
- 在mouseup事件中设置的接口行为时myDragUp,给其绑定行为方法,当鼠标抬起时,让两个图片进行为值互换;然后互换完,将其边框恢复原色;
- 知识点:
- 定位布局:定位元素的盒子模型(包括margin)相对于定位父级元素的内边框边缘进行定位;
- 定位元素的offsetLeft是元素的外边框到定位父级内边框边缘的距离;而添加定位的left值,是元素包含margin的整体相对于定位父级的内边框边缘的距离;
- 判断两个图片是否碰撞重合:判断四个边的位置比较,返回值为布尔值;
- 注意点:
- 图片的定位都是相对于外容器wrap定位;
- 浮动布局转化为定位布局时,注意margin的影响;需要将图片的margin值赋为0;
- 浮动布局转化为定位布局时,需要先获取位置值,在设置定位,遍历图片时,需要从最后一个开始转化,不然会出现覆盖问题;
- short的值问题,short必须设置为全局变量,这样在不同的函数中才能获取short值;
- ary数组为空的时候,代表没有重合的图片,则让其回到原来位置,但需要注意的是,sort在不断被重新赋值,所以在按下事件中,一定要给short赋值为null;如果数组为空时,也让short为null;
- 在交换的函数swapPos中,判断short是否存在,如果存在就互换位置值,设置位置值;如果不存在,则让图片回到原来位置;
- 代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>照片墙实例</title> <style> *{ margin: 0; padding: 0; } .wrap{ width: 792px; height: 462px; margin: 30px auto; background-color: lightskyblue; padding: 10px; position: relative; } .wrap img{ float: left; width: 250px; height: 140px; margin: 5px; border: 2px solid lightcoral; } </style> </head> <body> <div class="wrap" id="wrap"> <img src="img/1.jpg" alt=""> <img src="img/2.jpg" alt=""> <img src="img/3.jpg" alt=""> <img src="img/4.jpg" alt=""> <img src="img/5.jpg" alt=""> <img src="img/6.jpg" alt=""> <img src="img/7.jpg" alt=""> <img src="img/8.jpg" alt=""> <img src="img/9.jpg" alt=""> </div> <script src="JS/00utils.js"></script> <script src="JS/01Event.js"></script> <script src="JS/02Animate.js"></script> <script src="JS/04Drag.js"></script> <script> var oWrap=document.getElementById("wrap"); var aImg=oWrap.getElementsByTagName("img"); var zIndex=0; var short=null; for(var i=aImg.length-1; i>=0; i--){ //拖拽必须为定位布局,即将浮动布局转化为定位布局 var cur=aImg[i]; cur.style.left=(cur.l=cur.offsetLeft)+"px";//将位置保存在自己的私有属性上 cur.style.top=(cur.t=cur.offsetTop)+"px"; cur.style.position="absolute";//先获取位置,后设置定位; cur.style.margin=0; new Drag({ele:cur}).on("myDragDown",increaseZIndex).on("myDragMove",Collision).on("myDragUp",swapPos);//链式操作 } //按下时,提高层级 function increaseZIndex() { short=null; this.ele.style.borderColor="yellow"; this.ele.style.zIndex=++zIndex; } //比较两个图片是否碰撞,返回布尔值 function isCollision(img1,img2) { if((img1.offsetLeft+img1.offsetWidth<img2.offsetLeft) || (img1.offsetTop+img1.offsetHeight<img2.offsetTop) || (img1.offsetLeft>img2.offsetLeft+img2.offsetWidth) || (img1.offsetTop>img2.offsetTop+img2.offsetHeight)){ //四种情况只要有一种情况成立,就代表没有碰到 return false; }else{ return true; } } //移动过程中的判断 function Collision() { //此时this为实例对象,this.ele为当前移动的元素,与其他的所有图片进行比较 var ary=[]; for(var i=0; i<aImg.length; i++){ if(aImg[i]===this.ele) continue;//如果为移动图片本身就跳过此次循环; if(isCollision(this.ele,aImg[i])){ ary.push(aImg[i]); } } if(ary.length){ for(var i=0; i<ary.length; i++){ //将计算的值放在每个图片自定义属性身上 ary[i].dis=Math.sqrt(Math.pow(this.ele.offsetLeft-ary[i].offsetLeft,2)+Math.pow(this.ele.offsetTop-ary[i].offsetTop,2)); } //对计算的值进行排序,取最短的 ary.sort(function (a, b) { return a.dis-b.dis; }); short=ary[0]; short.style.borderColor="yellow"; for(var i=1; i<ary.length; i++){ ary[i].style.borderColor="lightcoral"; } }else{//如果ary为空,则将short赋值为空; if(short){short.style.borderColor="lightcoral";} short=null; } } function swapPos() { //互换位置,即让两个图片身上的自定义属性值互换,然后各自设置各自身上的值; if(short){//当short存在的时候让位置互换,不存在即为null则让其回原来位置; var tmp={}; tmp.l=this.ele.l; tmp.t=this.ele.t; this.ele.l=short.l; this.ele.t=short.t; short.l=tmp.l; short.t=tmp.t; /*animate({ ele:this.ele, target:{ left:this.ele.l, top:this.ele.t, }, duration: 500, effect: 2 });*/ short.style.zIndex=++zIndex; this.ele.style.zIndex=++zIndex; animate({ ele:short, target:{ left:short.l, top:short.t, }, duration: 500, effect: 2, callback:function () { this.style.borderColor="lightcoral"; } }); } //当short为null的时候,让元素回到自己位置 animate({ ele:this.ele, target:{ left:this.ele.l, top:this.ele.t, }, duration: 500, effect: 2, callback:function () { this.style.borderColor="lightcoral"; } }) } </script> </body> </html>
- 复习照片墙实例代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>照片墙实例复习</title> <style> *{ margin: 0; padding: 0; } h1{ width: 100%; height: 80px; line-height: 80px; text-align: center; } .container{ width: 800px; height: 470px; background-color: lightskyblue; padding: 10px; margin: 0 auto; box-sizing: border-box; } .container img{ float: left; width: 250px; height: 140px; margin: 5px; border: 2px solid lightcoral; box-sizing: border-box; } </style> </head> <body> <h1>美女照片墙</h1> <div class="container"> <img src="./img/1.jpg" alt="tu"/><img src="./img/2.jpg" alt="tu"/><img src="./img/3.jpg" alt="tu"/><img src="./img/4.jpg" alt="tu"/><img src="./img/5.jpg" alt="tu"/><img src="./img/6.jpg" alt="tu"/><img src="./img/7.jpg" alt="tu"/><img src="./img/8.jpg" alt="tu"/><img src="./img/9.jpg" alt="tu"/> </div> <script src="js/myutils.js"></script> <script src="js/myEvent.js"></script> <script src="js/finallyAnimate.js"></script> <script src="js/EventEmitter.js"></script> <script src="js/Drag.js"></script> <script> //获取元素 var oCon=utils.getByClass("container")[0]; var aImg=utils.getChildren(oCon,"img"); //如果使用拖拽必须为定位布局,所以需要将每个图片变为定位布局; //图片相对于外容器进行定位;所以外容器添加相对定位 toPosition(); function toPosition() { utils.css(oCon,"position","relative"); //从最后一个开始设置定位,获取其位置值 for(var i=aImg.length-1; i>=0;i--){ //先获取位置值,后设置绝对定位 aImg[i].initLeft=aImg[i].offsetLeft; aImg[i].initTop=aImg[i].offsetTop; utils.css(aImg[i],{ margin:0, position: "absolute", left:aImg[i].initLeft, top:aImg[i].initTop }) } } //图片添加拖拽功能 imgDrag(); function imgDrag() { for(var i=0; i<aImg.length; i++){ var drag=new Drag({ ele:aImg[i] }); drag.on("mymousedown",myDragdown).on("mymousemove",myDragmove).on("mymouseup",myDragup); } //myDragdown函数 function myDragdown() { //提高图片的层级 this.bgc=utils.css(this.ele,"borderColor"); utils.css(this.ele,{ borderColor:"yellow", zIndex:3 }); this.otherImg=utils.siblings(this.ele); } //myDragmove函数 function myDragmove() { this.ary=[]; for(var i=0; i<this.otherImg.length; i++){ //比较两个图片之间的位置 var tt=utils.offset(this.ele).top+this.ele.offsetHeight<utils.offset(this.otherImg[i]).top; var tb=utils.offset(this.ele).top>utils.offset(this.otherImg[i]).top+this.otherImg[i].offsetHeight; var rl=utils.offset(this.ele).left+this.ele.offsetWidth<utils.offset(this.otherImg[i]).left; var lr=utils.offset(this.ele).left>utils.offset(this.otherImg[i]).left+this.otherImg[i].offsetWidth; utils.css(this.otherImg[i],{ borderColor:this.bgc, zIndex:1 }); if(!(tt||tb||rl||lr)){ //计算出距离,绑定在元素的自定义属性上 this.otherImg[i].short=imgShort(this.ele,this.otherImg[i]); this.ary.push(this.otherImg[i]); } } //数组进行排序,排序目标为图片身上的short属性 if(this.ary.length>0){ this.ary.sort(function (a,b) { a=a.short; b=b.short; return a-b;//升序 }); //取最短的改变边框颜色,其他的恢复原边框颜色; utils.css(this.ary[0],{ borderColor:"yellow", zIndex:2 }); } //比较数组中的元素哪个与移动元素重合最多 //计算两个图片左上角点之间的距离,最短的,重合度越高 function imgShort(curImg,tarImg) { var curImgLeft=utils.offset(curImg).left; var curImgTop=utils.offset(curImg).top; var tarImgLeft=utils.offset(tarImg).left; var tarImgTop=utils.offset(tarImg).top; return Math.pow(tarImgLeft-curImgLeft,2)+Math.pow(tarImgTop-curImgTop,2); } } //myDragup function myDragup() { //鼠标抬起事件后,判断ary的长度 if(!this.ary){ utils.css(this.ele,"borderColor",this.bgc); return; } if(this.ary.length>0){ //如果数组不为空,就让移动元素与距离最短的互换位置; var l,t; l=this.ele.initLeft; t=this.ele.initTop; this.ele.initLeft=this.ary[0].initLeft; this.ele.initTop=this.ary[0].initTop; this.ary[0].initLeft=l; this.ary[0].initTop=t; } var othis=this; for(var i=0; i<aImg.length; i++){ animate({ ele:aImg[i], target:{ left:aImg[i].initLeft, top:aImg[i].initTop }, duration:300, callback:function () { utils.css(this,{ borderColor:othis.bgc, zIndex:1 }); othis.ary=null; } }) } } } </script> </body> </html>