Function description:
1. Supports two modes: automatic and manual: automatic rotation and display in automatic mode, selecting the current picture with the mouse in manual mode, or selecting the previous/next picture through the provided interface.
2. You can add the easing mode of rotation by yourself. The default mode is: uniform speed, first fast then slow, first slow then fast.
3. The width and height of the rotation track can be customized.
4. Support IE6 7 8 9 10 firefox chrome and other browsers.
Effect preview:
Implementation principle:
Based on the movement of the picture on the elliptical trajectory, dynamically change the zoom size to achieve a three-dimensional visual effect.
Code analysis:
Copy code The code is as follows:
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); }
The first is the initialization function, which contains defaultOptions as Default value, users can also pass in custom values. These parameter values include: container width, container height, picture width, picture height, maximum zoom factor, minimum zoom factor, rotation speed, etc. After initialization, call the setContainerSize function.
Copy code The code is as follows:
/* 设置容器尺寸 */ 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);//改变容器尺寸后改变旋转轨迹 },
The setContainerSize function sets the size of the container. The size of the container determines the rotation. The size of the trajectory. For example, when we set the height of the container to be equal to the width, the trajectory becomes a circle. After the container size is set, call the function changeRotateWH.
Copy code The code is as follows:
/* 改变椭圆旋转轨迹的横半轴长,竖半轴长*/ 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; //旋转竖半轴长 }
The function of changeRotateWH function is to set the ellipse rotation trajectory according to the size of the container. The horizontal half-axis length and the vertical half-axis length (halfRotateWidth and halfRotateHeight in the program, the specific calculation method is: track height = (container height - picture height)/2, track width = (container width - picture width)/2)) , in high school mathematics, we have learned the standard equation of the ellipse: (), where the horizontal and vertical semi-axes correspond to a and b of the elliptical equation respectively. Since this is an ellipse with a longer horizontal axis, a>b.
Copy the code The code is as follows:
/* 设置图片旋转角和初始位置,大小 */ 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); } }
After setting the basic coordinate system of the ellipse, we can adjust the number of images according to the number of images. , arrange the pictures into an elliptical shape. First, we can find the angle of the interval between the pictures through 2π/number of pictures, and then distribute the pictures evenly on the elliptical trajectory. At this time, all the pictures form an ellipse. Shape, here the initial distribution state of the picture comes out, and the next task is to make the picture move along this trajectory.
Copy code The code is as follows:
/* 设置图片位置和大小的匀速变化 */ var setImgPositionAndSize=function(img,path,direction){ direction=direction||'CW'; var dir=direction=='CW'?-1:1; img.RC+=(path*dir); modifyImgAngle(img); setImgSize(img); }
This function sets the corresponding size of the image according to the position of each image. , in addition we also need to pass in a parameter: direction (the value is CW (clockwise) or ACW (counterclockwise)), and then continue to increase the RC attribute (rotation angle) of the picture to make the picture automatically rotate at a constant speed, and then automatically rotate The rotation mode is ok.
Copy code The code is as follows:
/* 修改图片旋转角度(保证在0-2pai之间) */ var modifyImgAngle=function(img){ (img.RC>(2*Math.PI))&&(img.RC-=2*Math.PI); (img.RC<0)&&(img.RC+=2*Math.PI); }
Before the image is rotated, we can make an angle for each image A small modification is to limit the rotation angle to between 0-2π to facilitate subsequent calculations.
Copy code The code is as follows:
/* 设置图片大小和位置 */ 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); }
How to rotate the image according to the trajectory of the ellipse by changing the rotation angle? We can go back and look at the previous ellipse equation: (). Since what needs to be processed is rotation, we hope to convert the processing of x, y into the processing of rotation angle, so the x, y coordinates can be expressed as: x =a*cosα, y=b*sinα. The X coordinate of the image is expressed as: rotate.originX rotate.halfRotateWidth*Math.cos(img.RC)-imgWidth/2 (rotate.originX is the X coordinate of the origin, here we take the center point of the container), and the Y axis is the same. As mentioned before, the zoom size of the picture is based on the position of the picture, so the value of the scaling ratio scale is calculated based on the length of the vertical axis occupied by the y coordinate. In addition, the z-index of the hierarchical relationship is calculated based on the value of scale. The larger the size, the higher the level, is displayed in the front.
Copy code The code is as follows:
/* 设置旋转模式(自动/手动)*/ 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 Copy after login
完整的实现代码:
复制代码 代码如下:
<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>