기능 설명:
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); }
이 기능은 이미지 크기에 따라 해당 크기를 설정합니다. 또한 방향(값은 CW(시계 방향) 또는 ACW(반시계 방향)) 매개변수를 전달한 다음 그림의 RC 속성(회전 각도)을 계속 늘려야 합니다. 사진이 일정한 속도로 자동 회전한 다음 자동으로 회전합니다. 회전 모드는 괜찮습니다.
코드 복사 코드는 다음과 같습니다.
/* 修改图片旋转角度(保证在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 좌표는 다음과 같이 표현됩니다. ), Y축은 동일합니다. 앞서 언급한 바와 같이 사진의 줌 크기는 사진의 위치를 기준으로 하므로 스케일링 비율 스케일의 값은 y좌표가 차지하는 세로축의 길이를 기준으로 계산됩니다. 또한, scale 값을 기준으로 계층 관계의 z-index가 계산되어 크기가 클수록 상위 수준으로 표시됩니다.
코드 복사 코드는 다음과 같습니다.
/* 设置旋转模式(自动/手动)*/ 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完整的实现代码:
复制代码 代码如下:
<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>