您好,欢迎访问一九零五行业门户网

javascript椭圆旋转相册实现代码_图象特效

功能说明:
1.支持自动和手动两种模式:自动模式下自动旋转展示,手动模式下通过鼠标选择当前图片,或通过提供的接口选择上一张/下一张图片。
2.可自行添加旋转的缓动模式,默认模式为:匀速,先快后慢,先慢后快。
3.可自定义旋转轨迹的宽和高。
4.支持ie6 7 8 9 10 firefox chrome等浏览器。
效果预览:
实现原理:
根据对图片在椭圆轨迹上的运动,动态改变缩放大小,实现立体的视觉效果。
代码分析:
复制代码 代码如下:
init:function(id,options){ var defaultoptions={ width:600, //容器宽 height:200, //容器高 imgwidth:100, //图片宽 imgheight:60, //图片高 maxscale:1.5, //最大缩放倍数 minscale:0.5, //最小缩放倍数 rotatespeed:10 //运转速度 } options=util.extend(defaultoptions,options);//参数设置 this.container=util.$(id); this.width=options.width; this.height=options.height; imgwidth=this.imgwidth=options.imgwidth; imgheight=this.imgheight=options.imgheight; this.maxscale=options.maxscale; this.minscale=options.minscale; scalemargin=this.maxscale-this.minscale; this.rotatespeed=options.rotatespeed; this.imgs=util.$$('img',this.container); this.setcontainersize(this.width,this.height); initimgrc(this.imgs); }
首先是初始化函数,里面有defaultoptions作为默认值,用户也可以传入自定义的值,这些参数值包括:容器宽、容器高、图片宽、图片高、最大缩放倍数,最小缩放倍数,旋转速度等。初始化之后,调用setcontainersize函数。
复制代码 代码如下:
/* 设置容器尺寸 */ setcontainersize:function(width,height){ width=width||this.width; height=height||this.height; this.container.style.position='relative'; this.container.style.width=width+'px'; this.container.style.height=height+'px'; changerotatewh.call(this,width,height);//改变容器尺寸后改变旋转轨迹 },
setcontainersize函数设置了容器的尺寸,容器尺寸的大小决定了旋转轨迹的大小,例如当我们设置容器的高等于宽时,轨迹变成一个圆形。容器尺寸设定后,调用函数changerotatewh。
复制代码 代码如下:
/* 改变椭圆旋转轨迹的横半轴长,竖半轴长*/ var changerotatewh=function(width,height){ var halfscale=(this.maxscale-this.minscale)/2;//旋转到中间位置时的图片的缩放大小 rotate={}; rotate.originx=width/2;//旋转原点x轴坐标 rotate.originy=height/2;//旋转原点y轴坐标 rotate.halfrotatewidth=(width-this.imgwidth)/2; //旋转横半轴长 rotate.halfrotateheight=(height-this.imgheight)/2; //旋转竖半轴长 }
changerotatewh函数的作用是根据容器的尺寸,设定椭圆旋转轨迹的横半轴长和竖半轴长(程序里面的halfrotatewidth和halfrotateheight,具体计算方法为:轨迹高=(容器高-图片高)/2,轨迹宽=(容器宽-图片宽)/2)),在高中数学中,我们学过椭圆的标准方程:(),这里的横半轴和竖半轴分别对应椭圆方程的a和b。由于这里是横轴较长的椭圆,所以a>b。
复制代码 代码如下:
/* 设置图片旋转角和初始位置,大小 */ var initimgrc=function(imgs){ var len=imgs.length; con=(2*math.pi)/len; for(var i=0;i<len;i++){ imgs[i].rc=i*con; imgs[i].style.width=imgwidth+'px'; imgs[i].style.height=imgheight+'px'; setimgpositionandsize(imgs[i],0); } }
设置好椭圆的基本坐标系之后,我们可以根据图片的数量,把图片排列成一个椭圆的形状,首先我们可以通过 2π/图片数量 求得图片之间间隔所占的角度,然后把图片平均分布在椭圆轨迹上,此时所有图片就围成了一个椭圆的形状,到这里图片的初始分布状态就出来了,接下来的任务就是需要使图片沿着这个轨迹动起来。
复制代码 代码如下:
/* 设置图片位置和大小的匀速变化 */ var setimgpositionandsize=function(img,path,direction){ direction=direction||'cw'; var dir=direction=='cw'?-1:1; img.rc+=(path*dir); modifyimgangle(img); setimgsize(img); }
该函数根据每张图片位置的不同,设置图片对应的尺寸,另外我们还需要传入一个参数:direction(值为cw(顺时针)或acw(逆时针)),之后通过不断增加图片的rc属性(旋转角),使图片匀速自动旋转,这时自动旋转的旋转模式就ok了。
复制代码 代码如下:
/* 修改图片旋转角度(保证在0-2pai之间) */ var modifyimgangle=function(img){ (img.rc>(2*math.pi))&&(img.rc-=2*math.pi); (img.rc<0)&&(img.rc+=2*math.pi); }
在图片旋转之前,我们可以对每张图片的角度做一个小小的修改,把旋转角限定在0-2π之间,方便后续的计算。
复制代码 代码如下:
/* 设置图片大小和位置 */ var setimgsize=function(img){ var left=rotate.originx+rotate.halfrotatewidth*math.cos(img.rc)-imgwidth/2; var top=rotate.originy-rotate.halfrotateheight*math.sin(img.rc)-imgheight/2; var scale=minscale+scalemargin*(rotate.halfrotateheight-rotate.halfrotateheight*math.sin(img.rc))/(2*rotate.halfrotateheight);//图片在该时刻的缩放比 img.style.csstext='position:absolute;left:'+left+'px;' +'top:'+top+'px;' +'width:'+imgwidth*scale+'px;' +'height:'+imgheight*scale+'px;' +'z-index:'+math.round(scale*100); }
如何通过改变旋转角使图片按椭圆的轨迹旋转呢?我们可以再回过头看看之前的椭圆方程:(),由于需要处理的是旋转,所以我们希望把对x,y的处理转换成对旋转角度的处理,因此x,y坐标可以表示为:x=a*cosα , y=b*sinα 。图片的x坐标表示为:rotate.originx+rotate.halfrotatewidth*math.cos(img.rc)-imgwidth/2(rotate.originx为原点x坐标,这里取容器的中心点),y轴同理。之前说过图片缩放大小的依据是图片所处的位置,因此缩放比例scale的值则根据y坐标所占竖轴的长度进行计算。另外,层级关系z-index则根据scale的值进行计算,尺寸大得层级高,显示在前面。
复制代码 代码如下:
/* 设置旋转模式(自动/手动)*/ setpattern:function(patternname,option){ option=option||{}; this.pattern=patternname; var rotatespeed=option.rotatespeed||10; this.path=math.pi/1000*rotatespeed; (typeof timeid!='undefined')&&window.clearinterval(timeid); if(patternname==='auto'){//自动模式 可传入旋转方向:option.rotatedir 旋转速度:option.rotatespeed var self=this; var direction=option.rotatedir||'cw';//顺时针:cw 逆时针:acw removeimgshandler(this.imgs); timeid=window.setinterval(function(){ for(var i=0,len=self.imgs.length;i<len;i++){ setimgpositionandsize(self.imgs[i],self.path,direction); } },20); } else if(patternname==='hand'){//手动模式,可传回调函数:option.onselected 缓动模式:option.tween var onselected=option.onselected||util.emptyfunction; var tween=tween[tween]||tween['easeout'];//缓动模式默认为easeout removeimgshandler(this.imgs); (typeof timeid!='undefined')&&window.clearinterval(timeid); timeid=undefined; bindhandlerforimgs(this.imgs,this.path,tween,onselected); } } }
现在看看用户选择手动模式或者自动模式的接口:setpattern方法,该方法根据传入的字符串不同而选择不同的模式,“auto”为自动模式,该模式还可以传入自定义参数,包括旋转速度和旋转方向。传入“hand”则为手动模式,附加参数可以为手动选择图片后的回调函数,以及旋转的缓动模式。
复制代码 代码如下:
var tween = {//缓动类 默认提供三种缓动模式:linear easein easeout linear: function(t,b,c,d,dir){ return c*t/d*dir + b; }, easein: function(t,b,c,d,dir){ return c*(t/=d)*t*dir + b; }, easeout: function(t,b,c,d,dir){ return -c *(t/=d)*(t-2)*dir + b; } };
以上就是缓动模式类,默认的三个模式分别为:匀速 先慢后快 先快后慢。用户可以调用addtweenfunction方法添加自己的缓动模式。
复制代码 代码如下:
/* 添加缓动模式 */ addtweenfunction:function(name,func){ if(typeof func=='function'||typeof func=='object'){ tween[name]=func; } },
添加缓动模式的参数可以为对象或方法,一次性添加同类型的一组缓动模式建议使用对象添加。
复制代码 代码如下:
/* 为图片绑定点击事件处理程序 */ var bindhandlerforimgs=function(imgs,path,onselected){ for(var i=0,len=imgs.length;i<len;i++){ imgs[i].handler=imgselectedhandler(imgs,path,onselected); util.addeventhandler(imgs[i],'click',imgs[i].handler); } }
在手动模式下,首先要做的就是为图片绑定点击的事件处理程序,点击的图片沿着椭圆轨迹旋转移动到最前端,并且可以触发回调函数。
复制代码 代码如下:
/* 图片选择事件处理程序 */ var imgselectedhandler=function(imgs,path,tween,onselected){ return function(eve){ eve=eve||window.event; var dir; var angle; var target=eve.target||eve.srcelement; var rc=target.rc; if(rc>=math.pi/2&&rc<=math.pi*3/2){ dir='acw'; angle=3*math.pi/2-rc; } else{ dir='cw'; math.sin(rc)>=0?angle=math.pi/2+rc:angle=rc-3*math.pi/2; } (typeof timeid!='undefined')&&window.clearinterval(timeid); rotateangle(imgs,angle,dir,tween,onselected); } }
再看看手动模式下的核心函数,该函数作为事件处理程序,在点击选择图片后执行。首先判断所点击图片处在椭圆轨迹的左边还是右边,如果是左边,则旋转方向为逆时针,右边则为顺时针(为了符合最短移动路程的原则),之后调用 rotateangle使图片移动相应角度。
复制代码 代码如下:
/* 旋转指定角度 */ var rotateangle=function(imgs,angle,dir,tween,onselected){ var duration=1000; var starttime=(new date()).gettime(); dir=='cw'?dir=-1:dir=1; for(var i=0,len=imgs.length;i<len;i++){ imgs[i].startangle=imgs[i].rc; } timeid=window.setinterval(function(){ var now=(new date()).gettime(); if((now-starttime)>=duration){ window.clearinterval(timeid); timeid=undefined; onselected=onselected||util.emptyfunction; onselected();//触发回调函数; } for(var i=0,len=imgs.length;i<len;i++){ var path=tween(now-starttime,imgs[i].startangle,angle,duration,dir);//通过缓动公式计算新角度(rc) setpos(imgs[i],path,dir); } },20); }
rotateangle函数首先确定了旋转所经历的时间,图片的初始角度和开始旋转的时间,然后把一切工作交给缓动函数来计算图片下一次的旋转角度,缓动函数可以是用户设置的,也可以使用默认的easeout(先快后慢)。如果有回调函数的话,可以在旋转结束后触发。
复制代码 代码如下:
/* 选择上一幅图片 */ prepho:function(onselected){ if(this.pattern=='hand'){ onselected=onselected||util.emptyfunction; var tween=tween||tween['easeout']; if(typeof timeid!='undefined'){ return; }else{ rotateangle(this.imgs,con,'acw',tween,onselected); } } }, /* 选择下一幅图片 */ nextpho:function(onselected){ if(this.pattern=='hand'){ onselected=onselected||util.emptyfunction; var tween=tween||tween['easeout']; if(typeof timeid!='undefined'){ return; }else{ rotateangle(this.imgs,con,'cw',tween,onselected); } } },
另外在手动模式下,提供选择上一张图片和下一张图片的接口,原理就是使所有图片的旋转角度为图片之间的夹角,上一张图片和下一张图片的旋转方向分别设置为逆时针和顺时针。
复制代码 代码如下:
var rp=new rotatephos('container'); rp.setpattern('auto',{rotatespeed:10});//自动模式 旋转速度为10 rp.setpattern('hand');//手动模式
最后是调用方法初始化后需要设置旋转的模式。
说了一大堆不知道说清楚了没有,这里提供所有源码,有兴趣的童鞋可以看看哈~
源代码:
html:
复制代码 代码如下:
<p id="wrap" style="background:black;width:650px; height:250px; padding-top:20px; padding-left:20px;"> <p id="container"> <img src="pp.jpg" /> <img src="pp.jpg"/> <img src="pp.jpg"/> <img src="pp.jpg"/> <img src="pp.jpg"/> <img src="pp.jpg"/> <img src="pp.jpg" /> <img src="pp.jpg"/> <img src="pp.jpg"/> <img src="pp.jpg"/> <img src="pp.jpg"/> <img src="pp.jpg"/> </p> </p> <p> 手动模式:<input id="select" type="radio" name="sel" value="手动模式" onclick="rp.setpattern('hand');" checked="checked"/> 自动模式:<input id="select" type="radio" name="sel" value="自动模式" onclick="rp.setpattern('auto');" /> </p> <p> <input id="pre" type="button" value="上一张" /> <input id="next" type="button" value="下一张"/> </p>
js:
复制代码 代码如下:
var util = { $: function(sid) { return document.getelementbyid(sid); }, $$:function(tagname,parent){parent=parent||document; return parent.getelementsbytagname(tagname);}, addeventhandler: function(elem, type, handler) { if (elem.addeventlistener) { elem.addeventlistener(type, handler, false); } else { elem.attachevent("on" + type, handler); } }, removeeventhandler: function(elem, type, handler) { if (elem.removeeventlistener) { elem.removeeventlistener(type, handler, false); } else { elem.detachevent("on" + type, handler); } }, getcomputedstyle: function(elem) { if (elem.currentstyle) return elem.currentstyle; else { return document.defaultview.getcomputedstyle(elem, null); } }, getelementsbyclassname: function(classname, parentelement) { var elems = (parentelement || document.body).getelementsbytagname("*"); var result = []; for (i = 0; j = elems[i]; i++) { if ((" " + j.classname + " ").indexof(" " + classname + " ") != -1) { result.push(j); } } return result; }, extend: function(destination, source) { for (var name in source) { destination[name] = source[name]; } return destination; }, emptyfunction:function(){} }; var rotatephos=(function(){ var rp=function(id,options){ this.init(id,options);//初始化 } rp.prototype=(function(){ var rotate; var imgwidth; var imgheight; var scalemargin; var con; var handler; var minscale; var tween = {//缓动类 默认提供三种缓动模式:linear easein easeout linear: function(t,b,c,d,dir){ return c*t/d*dir + b; }, easein: function(t,b,c,d,dir){ return c*(t/=d)*t*dir + b; }, easeout: function(t,b,c,d,dir){ return -c *(t/=d)*(t-2)*dir + b; } }; /* 改变椭圆旋转轨迹的横半轴长,竖半轴长*/ var changerotatewh=function(width,height){ var halfscale=(this.maxscale-this.minscale)/2;//旋转到中间位置时的图片的缩放大小 rotate={}; rotate.originx=width/2;//旋转原点x轴坐标 rotate.originy=height/2;//旋转原点y轴坐标 rotate.halfrotatewidth=(width-this.imgwidth)/2; //旋转横半轴长 rotate.halfrotateheight=(height-this.imgheight)/2; //旋转竖半轴长 } /* 设置图片旋转角和初始位置,大小 */ var initimgrc=function(imgs){ var len=imgs.length; con=(2*math.pi)/len; for(var i=0;i<len;i++){ imgs[i].rc=i*con; imgs[i].style.width=imgwidth+'px'; imgs[i].style.height=imgheight+'px'; setimgpositionandsize(imgs[i],0); } } /* 设置图片大小和位置 */ var setimgsize=function(img){ var left=rotate.originx+rotate.halfrotatewidth*math.cos(img.rc)-imgwidth/2; var top=rotate.originy-rotate.halfrotateheight*math.sin(img.rc)-imgheight/2; var scale=minscale+scalemargin*(rotate.halfrotateheight-rotate.halfrotateheight*math.sin(img.rc))/(2*rotate.halfrotateheight);//图片在该时刻的缩放比 img.style.csstext='position:absolute;left:'+left+'px;' +'top:'+top+'px;' +'width:'+imgwidth*scale+'px;' +'height:'+imgheight*scale+'px;' +'z-index:'+math.round(scale*100); } /* 设置图片位置和大小的匀速变化 */ var setimgpositionandsize=function(img,path,direction){ direction=direction||'cw'; var dir=direction=='cw'?-1:1; img.rc+=(path*dir); modifyimgangle(img); setimgsize(img); } /* 修改图片旋转角度(保证在0-2pai之间) */ var modifyimgangle=function(img){ (img.rc>(2*math.pi))&&(img.rc-=2*math.pi); (img.rc<0)&&(img.rc+=2*math.pi); } /* 设置图片的新位置 */ var setpos=function(img,path){ img.rc=path; modifyimgangle(img); var left=rotate.originx+rotate.halfrotatewidth*math.cos(img.rc)-imgwidth/2; var top=rotate.originy-rotate.halfrotateheight*math.sin(img.rc)-imgheight/2; var scale=0.5+scalemargin*(rotate.halfrotateheight-rotate.halfrotateheight*math.sin(img.rc))/(2*rotate.halfrotateheight);//图片在该时刻的缩放比 img.style.csstext='position:absolute;left:'+left+'px;' +'top:'+top+'px;' +'width:'+imgwidth*scale+'px;' +'height:'+imgheight*scale+'px;' +'z-index:'+math.round(scale*100); } /* 旋转指定角度 */ var rotateangle=function(imgs,angle,dir,tween,onselected){ var duration=1000; var starttime=(new date()).gettime(); dir=='cw'?dir=-1:dir=1; for(var i=0,len=imgs.length;i<len;i++){ imgs[i].startangle=imgs[i].rc; } timeid=window.setinterval(function(){ var now=(new date()).gettime(); if((now-starttime)>=duration){ window.clearinterval(timeid); timeid=undefined; onselected=onselected||util.emptyfunction; onselected();//触发回调函数; } for(var i=0,len=imgs.length;i<len;i++){ var path=tween(now-starttime,imgs[i].startangle,angle,duration,dir);//通过缓动公式计算新角度(rc) setpos(imgs[i],path,dir); } },20); } /* 图片选择事件处理程序 */ var imgselectedhandler=function(imgs,path,tween,onselected){ return function(eve){ eve=eve||window.event; var dir; var angle; var target=eve.target||eve.srcelement; var rc=target.rc; if(rc>=math.pi/2&&rc<=math.pi*3/2){ dir='acw'; angle=3*math.pi/2-rc; } else{ dir='cw'; math.sin(rc)>=0?angle=math.pi/2+rc:angle=rc-3*math.pi/2; } (typeof timeid!='undefined')&&window.clearinterval(timeid); rotateangle(imgs,angle,dir,tween,onselected); } } /* 为图片绑定点击事件处理程序 */ var bindhandlerforimgs=function(imgs,path,onselected){ for(var i=0,len=imgs.length;i<len;i++){ imgs[i].handler=imgselectedhandler(imgs,path,onselected); util.addeventhandler(imgs[i],'click',imgs[i].handler); } } /* 删除图片上的点击事件处理程序 */ var removeimgshandler=function(imgs){ for(var i=0,len=imgs.length;i<len;i++){ if(imgs[i].handler){ util.removeeventhandler(imgs[i],'click',imgs[i].handler); } } } return{ /* 初始化 */ init:function(id,options){ var defaultoptions={ width:600, //容器宽 height:200, //容器高 imgwidth:100, //图片宽 imgheight:60, //图片高 maxscale:1.5, //最大缩放倍数 minscale:0.5, //最小缩放倍数 rotatespeed:10 //运转速度 } options=util.extend(defaultoptions,options);//参数设置 this.container=util.$(id); this.width=options.width; this.height=options.height; imgwidth=this.imgwidth=options.imgwidth; imgheight=this.imgheight=options.imgheight; this.maxscale=options.maxscale; minscale=this.minscale=options.minscale; scalemargin=this.maxscale-this.minscale; this.rotatespeed=options.rotatespeed; this.imgs=util.$$('img',this.container); this.setcontainersize(this.width,this.height); initimgrc(this.imgs); }, /* 设置容器尺寸 */ setcontainersize:function(width,height){ width=width||this.width; height=height||this.height; this.container.style.position='relative'; this.container.style.width=width+'px'; this.container.style.height=height+'px'; changerotatewh.call(this,width,height);//改变容器尺寸后改变旋转轨迹 }, /* 选择上一幅图片 */ prepho:function(onselected){ if(this.pattern=='hand'){ onselected=onselected||util.emptyfunction; var tween=tween||tween['easeout']; if(typeof timeid!='undefined'){ return; }else{ rotateangle(this.imgs,con,'acw',tween,onselected); } } }, /* 选择下一幅图片 */ nextpho:function(onselected){ if(this.pattern=='hand'){ onselected=onselected||util.emptyfunction; var tween=tween||tween['easeout']; if(typeof timeid!='undefined'){ return; }else{ rotateangle(this.imgs,con,'cw',tween,onselected); } } }, /* 添加缓动模式 */ addtweenfunction:function(name,func){ if(typeof func=='function'||typeof func=='object'){ tween[name]=func; } }, /* 设置旋转模式(自动/手动)*/ setpattern:function(patternname,option){ option=option||{}; this.pattern=patternname; var rotatespeed=option.rotatespeed||10; this.path=math.pi/1000*rotatespeed; (typeof timeid!='undefined')&&window.clearinterval(timeid); if(patternname==='auto'){//自动模式 可传入旋转方向:option.rotatedir 旋转速度:option.rotatespeed var self=this; var direction=option.rotatedir||'cw';//顺时针:cw 逆时针:acw removeimgshandler(this.imgs); timeid=window.setinterval(function(){ for(var i=0,len=self.imgs.length;i<len;i++){ setimgpositionandsize(self.imgs[i],self.path,direction); } },20); } else if(patternname==='hand'){//手动模式,可传回调函数:option.onselected 缓动模式:option.tween var onselected=option.onselected||util.emptyfunction; var tween=tween[tween]||tween['easeout'];//缓动模式默认为easeout removeimgshandler(this.imgs); (typeof timeid!='undefined')&&window.clearinterval(timeid); timeid=undefined; bindhandlerforimgs(this.imgs,this.path,tween,onselected); } } } })(); return rp; })(); var rp=new rotatephos('container'); //rp.setpattern('auto',{rotatespeed:10}); rp.setpattern('hand'); document.getelementbyid('pre').onclick=function(){rp.prepho();}; document.getelementbyid('next').onclick=function(){rp.nextpho();};
完整的实现代码:
复制代码 代码如下:
<p id="wrap" style="background: black; width: 800px; height: 350px; padding-top: 20px; padding-left: 20px; padding-right: 20px;"> <p id="container"><img src="http://files.jb51.net/upload/201201/20120116231926539.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231926632.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231926661.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231926763.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231926174.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231926604.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231927431.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231927666.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231927424.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231927108.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231927843.jpg" alt="" /> <img src="http://files.jb51.net/upload/201201/20120116231927662.bmp" alt="" /></p> </p> <p>手动模式:<input id="select" onclick="rp.setpattern('hand');" type="radio" name="sel" value="手动模式" /> 自动模式:<input id="select" onclick="rp.setpattern('auto');" type="radio" name="sel" value="自动模式" /></p> <p><input id="pre" type="button" value="上一张" /> <input id="next" type="button" value="下一张" /></p> <p> <script type="text/javascript">// <![cdata[ var rotatephos = (function() { var util = { $: function(sid) { return document.getelementbyid(sid); }, $$: function(tagname, parent) { parent = parent || document; return parent.getelementsbytagname(tagname); }, addeventhandler: function(elem, type, handler) { if (elem.addeventlistener) { elem.addeventlistener(type, handler, false); } else { elem.attachevent("on" + type, handler); } }, removeeventhandler: function(elem, type, handler) { if (elem.removeeventlistener) { elem.removeeventlistener(type, handler, false); } else { elem.detachevent("on" + type, handler); } }, getcomputedstyle: function(elem) { if (elem.currentstyle) return elem.currentstyle; else { return document.defaultview.getcomputedstyle(elem, null); } }, emptyfunction: function() { }, getelementsbyclassname: function(classname, parentelement) { var elems = (parentelement || document.body).getelementsbytagname("*"); var result = []; for (i = 0; j = elems[i]; i++) { if ((" " + j.classname + " ").indexof(" " + classname + " ") != -1) { result.push(j); } } return result; }, extend: function(destination, source) { for (var name in source) { destination[name] = source[name]; } return destination; } }; var rp = function(id, options) { this.init(id, options); //初始化 } rp.prototype = (function() { var rotate; var imgwidth; var imgheight; var scalemargin; var con; var handler; var tween = {//缓动类 默认提供三种缓动模式:linear easein easeout linear: function(t, b, c, d, dir) { return c * t / d * dir + b; }, easein: function(t, b, c, d, dir) { return c * (t /= d) * t * dir + b; }, easeout: function(t, b, c, d, dir) { return -c * (t /= d) * (t - 2) * dir + b; } }; /* 改变椭圆旋转轨迹的横半轴长,竖半轴长*/ var changerotatewh = function(width, height) { var halfscale = (this.maxscale - this.minscale) / 2; //旋转到中间位置时的图片的缩放大小 rotate = {}; rotate.originx = width / 2; //旋转原点x轴坐标 rotate.originy = height / 2; //旋转原点y轴坐标 rotate.halfrotatewidth = (width - this.imgwidth) / 2; //旋转横半轴长 rotate.halfrotateheight = (height - this.imgheight) / 2; //旋转竖半轴长 } /* 设置图片旋转角和初始位置,大小 */ var initimgrc = function(imgs) { var len = imgs.length; con = (2 * math.pi) / len; for (var i = 0; i < len; i++) { imgs[i].rc = i * con; imgs[i].style.width = imgwidth + 'px'; imgs[i].style.height = imgheight + 'px'; setimgpositionandsize(imgs[i], 0); } } /* 设置图片大小 */ var setimgsize = function(img) { var left = rotate.originx + rotate.halfrotatewidth * math.cos(img.rc) - imgwidth / 2; var top = rotate.originy - rotate.halfrotateheight * math.sin(img.rc) - imgheight / 2; var scale = 0.5 + scalemargin * (rotate.halfrotateheight - rotate.halfrotateheight * math.sin(img.rc)) / (2 * rotate.halfrotateheight); //图片在该时刻的缩放比 img.style.csstext = 'position:absolute;left:' + left + 'px;' + 'top:' + top + 'px;' + 'width:' + imgwidth * scale + 'px;' + 'height:' + imgheight * scale + 'px;' + 'cursor:pointer;' + 'z-index:' + math.round(scale * 100); } /* 设置图片位置和大小的匀速变化 */ var setimgpositionandsize = function(img, path, direction) { direction = direction || 'cw'; var dir = direction == 'cw' ? -1 : 1; img.rc += (path * dir); modifyimgangle(img); setimgsize(img); } /* 修改图片旋转角度(保证在0-2pai之间) */ var modifyimgangle = function(img) { (img.rc > (2 * math.pi)) && (img.rc -= 2 * math.pi); (img.rc < 0) && (img.rc += 2 * math.pi); } /* 设置图片的新位置 */ var setpos = function(img, path) { img.rc = path; modifyimgangle(img); var left = rotate.originx + rotate.halfrotatewidth * math.cos(img.rc) - imgwidth / 2; var top = rotate.originy - rotate.halfrotateheight * math.sin(img.rc) - imgheight / 2; var scale = 0.5 + scalemargin * (rotate.halfrotateheight - rotate.halfrotateheight * math.sin(img.rc)) / (2 * rotate.halfrotateheight); //图片在该时刻的缩放比 img.style.csstext = 'position:absolute;left:' + left + 'px;' + 'top:' + top + 'px;' + 'width:' + imgwidth * scale + 'px;' + 'height:' + imgheight * scale + 'px;' + 'z-index:' + math.round(scale * 100); } /* 旋转指定角度 */ var rotateangle = function(imgs, angle, dir, tween, onselected) { var duration = 1000; var starttime = (new date()).gettime(); dir == 'cw' ? dir = -1 : dir = 1; for (var i = 0, len = imgs.length; i < len; i++) { imgs[i].startangle = imgs[i].rc; } timeid = window.setinterval(function() { var now = (new date()).gettime(); if ((now - starttime) >= duration) { window.clearinterval(timeid); timeid = undefined; onselected = onselected || util.emptyfunction; onselected(); //触发回调函数; } for (var i = 0, len = imgs.length; i < len; i++) { var path = tween(now - starttime, imgs[i].startangle, angle, duration, dir); //通过缓动公式计算新角度(rc) setpos(imgs[i], path, dir); } }, 20); } /* 图片选择事件处理程序 */ var imgselectedhandler = function(imgs, path, tween, onselected) { return function(eve) { eve = eve || window.event; var dir; var angle; var target = eve.target || eve.srcelement; var rc = target.rc; if (rc >= math.pi / 2 && rc <= math.pi * 3 / 2) { dir = 'acw'; angle = 3 * math.pi / 2 - rc; } else { dir = 'cw'; math.sin(rc) >= 0 ? angle = math.pi / 2 + rc : angle = rc - 3 * math.pi / 2; } (typeof timeid != 'undefined') && window.clearinterval(timeid); rotateangle(imgs, angle, dir, tween, onselected); } } /* 为图片绑定点击事件处理程序 */ var bindhandlerforimgs = function(imgs, path, onselected) { for (var i = 0, len = imgs.length; i < len; i++) { imgs[i].handler = imgselectedhandler(imgs, path, onselected); util.addeventhandler(imgs[i], 'click', imgs[i].handler); } } /* 删除图片上的点击事件处理程序 */ var removeimgshandler = function(imgs) { for (var i = 0, len = imgs.length; i < len; i++) { if (imgs[i].handler) { util.removeeventhandler(imgs[i], 'click', imgs[i].handler); } } } return { /* 初始化 */ init: function(id, options) { var defaultoptions = { width: 700, //容器宽 height: 300, //容器高 imgwidth: 130, //图片宽 imgheight: 80, //图片高 maxscale: 1.5, //最大缩放倍数 minscale: 0.5, //最小缩放倍数 rotatespeed: 10 //运转速度 } options = util.extend(defaultoptions, options); //参数设置 this.container = util.$(id); this.width = options.width; this.height = options.height; imgwidth = this.imgwidth = options.imgwidth; imgheight = this.imgheight = options.imgheight; this.maxscale = options.maxscale; this.minscale = options.minscale; scalemargin = this.maxscale - this.minscale; this.rotatespeed = options.rotatespeed; this.imgs = util.$$('img', this.container); this.setcontainersize(this.width, this.height); initimgrc(this.imgs); }, /* 设置容器尺寸 */ setcontainersize: function(width, height) { width = width || this.width; height = height || this.height; this.container.style.position = 'relative'; this.container.style.width = width + 'px'; this.container.style.height = height + 'px'; changerotatewh.call(this, width, height); //改变容器尺寸后改变旋转轨迹 }, /* 选择上一幅图片 */ prepho: function(onselected) { if (this.pattern == 'hand') { onselected = onselected || util.emptyfunction; var tween = tween || tween['easeout']; if (typeof timeid != 'undefined') { return; } else { rotateangle(this.imgs, con, 'acw', tween, onselected); } } }, /* 选择下一幅图片 */ nextpho: function(onselected) { if (this.pattern == 'hand') { onselected = onselected || util.emptyfunction; var tween = tween || tween['easeout']; if (typeof timeid != 'undefined') { return; } else { rotateangle(this.imgs, con, 'cw', tween, onselected); } } }, /* 添加缓动模式 */ addtweenfunction: function(name, func) { if (typeof func == 'function' || typeof func == 'object') { tween[name] = func; } }, /* 设置旋转模式(自动/手动)*/ setpattern: function(patternname, option) { option = option || {}; this.pattern = patternname; var rotatespeed = option.rotatespeed || 10; this.path = math.pi / 1000 * rotatespeed; (typeof timeid != 'undefined') && window.clearinterval(timeid); if (patternname === 'auto') {//自动模式 可传入旋转方向:option.rotatedir 旋转速度:option.rotatespeed var self = this; var direction = option.rotatedir || 'cw'; //顺时针:cw 逆时针:acw removeimgshandler(this.imgs); timeid = window.setinterval(function() { for (var i = 0, len = self.imgs.length; i < len; i++) { setimgpositionandsize(self.imgs[i], self.path, direction); } }, 20); } else if (patternname === 'hand') {//手动模式,可传回调函数:option.onselected 缓动模式:option.tween var onselected = option.onselected || util.emptyfunction; var tween = tween[tween] || tween['easeout']; //缓动模式默认为easeout removeimgshandler(this.imgs); (typeof timeid != 'undefined') && window.clearinterval(timeid); timeid = undefined; bindhandlerforimgs(this.imgs, this.path, tween, onselected); } } } })(); return rp; })(); var rp=new rotatephos('container'); //rp.setpattern('auto',{rotatespeed:10}); rp.setpattern('hand'); document.getelementbyid('pre').onclick=function(){rp.prepho();}; document.getelementbyid('next').onclick=function(){rp.nextpho();}; // ]]></script> </p>
其它类似信息

推荐信息