面向对象编写照片墙组件

来源:互联网 发布:搜番软件 编辑:程序博客网 时间:2024/05/29 12:18

面向对象是一种优秀的编程思想,在JS中亦是如此,在大规模的项目中,体现的愈加突出。对于一些常用功能来说,我们完全可以将其开发成一个组件,比如JQuery中的弹窗组件等,我们可以很方便使用它们,使用时只需要按照API要求填写对应配置参数,即可迅速使用。本文给大家分享一个简单的照片墙组件。该照片墙组件完全原生JS实现,功能比较简单,但实现了一般照片墙的基本效果。我们可以通过构造函数PhotoWall()实例化一个对象,并调用init()方法进行初始化。对于布局样式要求极低,甚至完全不用设置。用户可以按照自身需求喜好随意放置照片墙的位置。预览最终效果以及下载文件,请点击这里。以下是使用该组件的具体实现方法:

首先进行一些简单的布局:

<!DOCTYPE html><html><head><meta charset="UTF-8"><title>动态照片墙</title><style type="text/css">#photoList{width: 660px;position: relative;margin: 10px auto;}#photoList li{float: left;width: 200px;height: 150px;margin: 10px;list-style: none;}</style><script src="photoWall.js"></script><script type="text/javascript">window.onload=function(){//创建对象var p1=new PhotoWall();//初始化方法p1.init({//配置参数ulId:'photoList',btnId:'randomBtn',speed:12});}</script></head><body><!--随机按钮id取为'randomBtn',照片ul的id取为'photoWall'--><ul id="photoList"><li><img src="img/1.png"/></li><li><img src="img/2.png"/></li><li><img src="img/3.png"/></li><li><img src="img/4.png"/></li><li><img src="img/5.png"/></li><li><img src="img/1.png"/></li><li><img src="img/2.png"/></li><li><img src="img/3.png"/></li><li><img src="img/4.png"/></li></ul><input type="button" name="btn1" id="randomBtn" value="随机" /></body></html>
然后我们来看一下具体的JS实现代码:

/* 
 * 面向对象照片墙
 * 使用构造函数PhotoWall()来创建一个对象
 * 使用init()方法初始化
 * init()发放接收默认配置参数形式为:
 * init({
 * ulId:'xxx',必填项,需初始化的对象ul的id
 * btnId:null,选填项,随机按钮的id,多个照片墙不能绑定同一按钮
 * speed:8 选填项,图片交换速度
 * })
*/

//构造函数PhotoWall()function PhotoWall(){//用以设置每张图片的zIndexthis.izIndex=2;//用以存放每张图片的初始位置this.arr=[];//用以保存鼠标在图片上的位置this.disX=null;this.disY=null;//默认参数this.settings={ulId:'photoList',btnId:null,speed:8};}
/*
 * init()初始化方法:
 * 由于存在点击事件,所以使用This提前保存对象,用以修正this指向
 * 调用exchange()方法用配置参数项修改默认参数
 * 使用修改后的参数获取页面布局元素(ul、li)
 * 如果随机按钮存在,则为随机按钮添加点击事件
 * 为每一个li循环添加拖拽事件
 */

PhotoWall.prototype.init=function(opt){var This=this;this.exchange(this.settings,opt);this.oUl=document.getElementById(this.settings.ulId);this.aLi=this.oUl.getElementsByTagName('li');if(this.settings.btnId){this.oBtn=document.getElementById(this.settings.btnId);this.oBtn.onclick=function(){This.randomBtn();};}for(var i=0;i<this.aLi.length;i++){this.setList();this.aLi[i].index=i;this.drag(this.aLi[i]);}}
/*
 * exchange()方法:
 * for-in循环遍历配置参数
 * 相同项将会使用配置参数进行覆盖
 * 未设置的参数选项将会保持默认参数
 */
PhotoWall.prototype.exchange=function(obj1,obj2){for(var attr in obj2){obj1[attr]=obj2[attr];}}
/* 
 * setList()方法:
 * CSS中初始为浮动定位,为每一个图片确定一个初始位置
 * 第一个for循环,将每张图的初始位置以[left,top]的形式存于arr数组
 * 第二个for循环,将每张图的浮动形式的位置转化为绝对定位的位置
 * 由于转化时的值已经包含了margin值,故清除CSS的margin值
*/
PhotoWall.prototype.setList=function(){for(var i=0;i<this.aLi.length;i++){this.arr[i]=[this.aLi[i].offsetLeft,this.aLi[i].offsetTop];}for(var i=0;i<this.aLi.length;i++){this.aLi[i].style.position='absolute';this.aLi[i].style.left=this.arr[i][0]+'px';this.aLi[i].style.top=this.arr[i][1]+'px';this.aLi[i].style.margin=0;}}
/*
 * randomBtn()方法:
 * 定义数组arr2存放index索引,判断图片个数,进行push操作
 * 目的是保证最终图片依旧按索引顺序排放,即1、2、3、4、5···
 * 将数组索引随机排序,然后使用for循环按照数组顺序排序,并修正索引值
 */

PhotoWall.prototype.randomBtn=function(){var arrRandom=new Array();for(var i=0;i<this.aLi.length;i++){arrRandom.push(i);}arrRandom.sort(function(){return Math.random()-0.5;})for(var i=0;i<this.aLi.length;i++){this.startMove(this.aLi[i],{ left: this.arr[arrRandom[i]][0] ,top:this.arr[arrRandom[i]][1]});this.aLi[i].index=arrRandom[i];}}
/*
 * drag()、mouseDown()、docMove()、docUp()
 * 共同构成拖拽事件处理办法
 */
PhotoWall.prototype.drag=function(obj){//为onmousedown事件修正this指向var This=this;//为对象添加onmousedown事件obj.onmousedown=function(ev){var ev=ev||event;This.mouseDown(ev,obj);return false;};}
//onmousedown处理方法PhotoWall.prototype.mouseDown=function(ev,obj){//为onmousemove事件修正this指向var This=this;//保存鼠标在图片上点击的位置this.disX=ev.clientX-obj.offsetLeft;this.disY=ev.clientY-obj.offsetTop;//当前点击图片index加一,保证点击的图片处于最上层obj.style.zIndex=this.izIndex++;//点击对象后,为文档添加onmousemove事件document.onmousemove=function(ev){var ev=ev||event;This.docMove(ev,obj);};//点击对象后,为文档添加onmouseup事件document.onmouseup=function(){This.docUp(obj);};}//onmousemove处理方法PhotoWall.prototype.docMove=function(ev,obj){var ev=ev||event;var n1=this.nears(obj);//点击对象后,如果文档上发生onmousemove事件时,随之更改图片位置obj.style.left=ev.clientX-this.disX+'px';obj.style.top=ev.clientY-this.disY+'px';//清除所有的图片红框for(var i=0;i<this.aLi.length;i++){this.aLi[i].style.border="";}//如果最近的图片存在,则为其添加红框if(n1){n1.style.border="1px solid red";}}//onmouseup处理方法PhotoWall.prototype.docUp=function(obj){//鼠标抬起时,清除文档的onmousemove与onmouseup事件document.onmousemove=null;document.onmouseup=null;//获取所有与当前对象发生碰撞中的距离最近的对象var n1=this.nears(obj);var temp=null;//如果存在一个发生碰撞并且距离最近的元素,则与其交换位置,并交换索引值,清除红框if(n1){this.startMove(obj,{ left: this.arr[n1.index][0] ,top:this.arr[n1.index][1]});this.startMove(n1,{ left: this.arr[obj.index][0] ,top:this.arr[obj.index][1]});temp=obj.index;obj.index=n1.index;n1.index=temp;n1.style.border="";}//否则回到自己原来位置else{this.startMove(obj,{left:this.arr[obj.index][0],top:this.arr[obj.index][1]});}}
/*
 * nears()方法:
 * 用于寻找距离最近的一个图片对象
 * 所有距离值与value比较,一直保存最小的值,保存最小值的索引值
 * 如果存在最小距离,则返回最小距离的这个图片对象
 */
PhotoWall.prototype.nears=function(obj){var value=99999;var iIndex=-1;for(var i=0;i<this.aLi.length;i++){if(this.pz(obj,this.aLi[i])&&obj!=this.aLi[i]){var c=this.jl(obj,this.aLi[i]);if(c<value){value=c;iIndex=i;}}}if(iIndex!=-1){return this.aLi[iIndex];}else{return false;}}
/*
 * jl()方法:
 * 勾股定理计算并返回两图片对象的中心距离
 */
PhotoWall.prototype.jl=function(obj1,obj2){var a=obj1.offsetLeft-obj2.offsetLeft;var b=obj1.offsetTop-obj2.offsetTop;return Math.sqrt(a*a+b*b);}
/*
 * pz()方法
 * 用以检测两对象是否发生碰撞,若碰撞则返回true
 */
PhotoWall.prototype.pz=function(obj1,obj2){var t1=obj1.offsetTop;var b1=obj1.offsetTop+obj1.offsetHeight;var l1=obj1.offsetLeft;var r1=obj1.offsetLeft+obj1.offsetWidth;var t2=obj2.offsetTop;var b2=obj2.offsetTop+obj2.offsetheight;var l2=obj2.offsetLeft;var r2=obj2.offsetLeft+obj2.offsetWidth;if(r1<l2||l1>r2||t1>b2||b1<t2){return false;}else{return true;}}
/*
 * startMove()与getStyle()方法为运动框架
 * 接收两个个参数
 * obj:运动的对象
 * json:一个json值对,保存运动的目标点(left,top)
 */
PhotoWall.prototype.startMove=function(obj,json){var This=this;clearInterval(obj.timer);obj.timer = setInterval(function(){var bBtn = true;for(var attr in json){var iCur = 0;if(attr == 'opacity'){if(Math.round(parseFloat(This.getStyle(obj,attr))*100)==0){iCur = Math.round(parseFloat(This.getStyle(obj,attr))*100);}else{iCur = Math.round(parseFloat(This.getStyle(obj,attr))*100) || 100;}}else{iCur = parseInt(This.getStyle(obj,attr)) || 0;}var iSpeed = (json[attr] - iCur)/This.settings.speed;iSpeed = iSpeed >0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);if(iCur!=json[attr]){bBtn = false;}if(attr == 'opacity'){obj.style.filter = 'alpha(opacity=' +(iCur + iSpeed)+ ')';obj.style.opacity = (iCur + iSpeed)/100;}else{obj.style[attr] = iCur + iSpeed + 'px';}}if(bBtn){clearInterval(obj.timer);}},30);}PhotoWall.prototype.getStyle=function(obj,attr){if(obj.currentStyle){return obj.currentStyle[attr];}else{return getComputedStyle(obj,false)[attr];}}
这样一个简化的照片墙就算完成了,可以根据自己的需要进行添加方法。如有任何疑问,欢迎提出!

1 0
原创粉丝点击