第十一周第二天笔记之照片墙实例

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>
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 14,697评论 1 92
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 28,404评论 1 45
  • 学会使用CSS选择器熟记CSS样式和外观属性熟练掌握CSS各种选择器熟练掌握CSS各种选择器熟练掌握CSS三种显示...
    七彩小鹿阅读 11,445评论 2 66
  • 概述 在网易云课堂学习李南江老师的《从零玩转HTML5前端+跨平台开发》时,所整理的笔记。笔记内容为根据个人需求所...
    墨荀阅读 6,988评论 0 7
  • 很多学平面设计的人都会遇到一个问题,那就是学平面设计需要学手绘吗?手绘这个问题是很多学员一直关注的问题,那么学平面...
    黑色星期九阅读 12,327评论 0 0

友情链接更多精彩内容