功能说明:
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

  设置好椭圆的基本坐标系之后,我们可以根据图片的数量,把图片排列成一个椭圆的形状,首先我们可以通过 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-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

  现在看看用户选择手动模式或者自动模式的接口: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方法添加自己的缓动模式。
  更多关于缓动的话题可以参考这两篇文章:
  http://zengrong.net/post/1151.htm
  http://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html
/* 添加缓动模式 */ 
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

  在手动模式下,首先要做的就是为图片绑定点击的事件处理程序,点击的图片沿着椭圆轨迹旋转移动到最前端,并且可以触发回调函数。
/* 图片选择事件处理程序 */ 
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=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=duration){ 
window.clearInterval(timeId); 
timeId=undefined; 
onSelected=onSelected||util.emptyFunction; 
onSelected();//触发回调函数; 
} 
for(var i=0,len=imgs.length;i

   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:

手动模式: 自动模式:


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(2*Math.PI))&&(img.RC-=2*Math.PI); 
(img.RC=duration){ 
window.clearInterval(timeId); 
timeId=undefined; 
onSelected=onSelected||util.emptyFunction; 
onSelected();//触发回调函数; 
} 
for(var i=0,len=imgs.length;i=Math.PI/2&&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

完整的实现代码:

手动模式: 自动模式:

javascript椭圆旋转相册实现代码的更多相关文章

  1. ios – CAShapeLayer动画路径毛刺/闪烁(从椭圆到矩形和背面)

    当我创建一个显式动画来将CAShapeLayer的路径值从椭圆更改为矩形时,我遇到了一个问题.在我的画布控制器中,我设置了一个基本的CAShapeLayer并将其添加到根视图的图层:然后,当我为路径设置动画时,在动画的最后几帧中,当形状变为矩形时会出现奇怪的毛刺/闪烁,而在前几帧中,当动画远离矩形时,会出现奇怪的毛刺/闪烁.动画设置如下:我尝试了很多不同的东西,比如锁定/解锁CATransaction,玩各种填充模式等等……

  2. android – 使用marquee ellipsize在TextView上设置textIsSelectable会添加椭圆

    我的应用程序中的屏幕可能会将非常长的字符串发布到TextView中.对于这种情况,我有android:ellipsize=“marquee”设置,因此文本将在TextView上进行选取.但是,我已经决定我也希望这个文本可以选择.在大多数情况下,这没有问题.文本小于TextView,用户可以选择它.但是,如果我有textIsSelectable属性,并且文本大于TextView,则文本将拾取椭圆而不是完整字符串.它仍然是大帐篷,但它不再显示全文.它切断它并显示一个椭圆.有没有办法让文本可选并仍然保持整个字符

  3. android – 在画布上的文本周围绘制一个椭圆形状

    我想在Canvas上的文本周围画一个椭圆形,我正在使用drawwText()方法在Canvas上显示3个文本.现在,当我单击特定文本时,我需要在该文本周围绘制一个椭圆,当我们单击另一个文本时,椭圆形状应该出现在单击的文本上.为此,给我一些代码建议.谢谢你提前解决方法使用drawoval方法()..这里是方法的签名..RectF是绘制矩形的类…其构造函数定义如下…你可以使它的对象如下现在在drawoval方法中传递此对象…

  4. javascript椭圆旋转相册实现代码

    支持自动和手动两种模式:自动模式下自动旋转展示,手动模式下通过鼠标选择当前图片,或通过提供的接口选择上一张/下一张图片

  5. wpf – 如何用椭圆类画一个圆圈?

    我想在WP7上制作一个圈子。我试图用椭圆类做这个,我发现了很多解决方案,这是一个规格或饼图或者一些东西,但我只需要精华。目的是显示一个圆(或椭圆)的一部分。像图片中的黄色区域:谢谢,拉奇这是一个相当简单的解决方案,虽然它不使用椭圆,它需要一个三角学:Data属性使用PathMarkupSyntax。>开始时的“M”告诉笔移动到位置0,0。>“L”指示笔从当前位置(0,0)画一条线为0,-100。>“A”指示笔将当前位置的椭圆弧画为70.7,-70.7。

  6. 在Delphi 2010中绘制不透明度椭圆

    我期待在CodeGearDelphi2010中绘制一个不透明椭圆.我试图绘制另一个位图,我设置了位图透明色(用于背景)调用椭圆方法.在我的图像中,我使用不透明度参数(来自重载)绘制位图.但它不起作用.我想要这样的东西http://www.java2s.com/Tutorial/VBImages/WPF-UseOpacityMaskAndRadialGradientBrush.PNG有人知道一种工作

  7. javascript – Canvas:arc(75,75,50,0,3.1415,true)绘制椭圆而不是圆

    为什么这个代码在半径为50的位置绘制椭圆而不是圆?解决方法如果您更改此行:至:它应该工作.不要使用CSS来设置Canvas大小,因为这只会影响元素而不影响位图本身.对于画布,您需要使用它的专用属性来设置位图大小,或者只是拉伸/缩放位图以匹配元素的大小.如果未指定,则画布的默认大小为300×150像素.在这种情况下,这些像素被拉伸到400×400,这就是为什么你得到一个椭圆形.

  8. 在Objective-C中绘制具有起始和结束角度的椭圆

    我正在编写一个iPad应用程序,我在其中渲染表示形状的XML对象到屏幕上的图形.我试图渲染的对象之一是弧.基本上这些弧为我提供了一个边界矩形以及一个开始和结束角度.给定属性:>x>y>宽度>身高>startAngle>endAngle使用这些值,我需要绘制弧(基本上是椭圆的一部分).我不能使用以下内容:因为它绘制了一个完整的椭圆.基本上我需要上面但是它需要考虑开始和结束角度,因此只显示椭圆的一部分

  9. jQuery datepicker – 当鼠标悬停在小日历图标上时如何关闭椭圆工具提示

    我正在使用带有图标的日期选择器(小日历).当我用鼠标将鼠标悬停在它上面然后点击它以获得日期选择器日历时,在所有浏览器中出现一个带有椭圆的恼人小灰色框(工具提示?我在thisdemopagefortheplug-in看到它,所以它不仅仅是我的代码.它必须是默认值,因为我没有在任何地方设置它,也看不到在哪里设置或重置它.如何将其关闭或用有意义的东西替换椭圆?要在工具提示中显示“日历”,该选项应为:要摆脱工具提示,选项应该是:完整代码如下:JQuery的

  10. java – 使用OpenCV进行椭圆检测

    我想用OpenCVforAndroid检测椭圆,使用OpenCV2.4.1软件包附带的Tutorial2-Basic作为起点.请注意,我的椭圆将是一个完美的Photoshop.从我所理解的,使用“霍克圆圈”只会找到完美的(或许)圆圈,从而将椭圆偏离.任何帮助将不胜感激,因为我是OpenCV的初学者这是我迄今为止所尝试的如果您认为更多的信息可能有用,请让我知道.解决方法你的问题的一个可能的解决方案是类似于这个线程Detectionofcoinsonanimage.你应该看看opencv的功能fitEllip

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部