JavaScript 楕円回転フォト アルバム実装コード_画像特殊効果

不言
リリース: 2018-05-28 17:16:19
オリジナル
2992 人が閲覧しました

機能の説明:
1. 自動と手動の 2 つのモードをサポートします。自動モードでは自動回転および表示、手動モードではマウスで現在の画像を選択するか、提供されたインターフェイスを通じて前/次の画像を選択します。
2. 回転のイージング モードを自分で追加できます。デフォルトのモードは、均一速度、最初に高速、次に低速です。
3. 回転トラックの幅と高さをカスタマイズできます。
4. IE6 7 8 9 10 Firefox Chrome およびその他のブラウザをサポートします。
効果プレビュー:
JavaScript 楕円回転フォト アルバム実装コード_画像特殊効果
実装原理:
楕円軌道上の画像の動きに基づいて、ズーム サイズを動的に変更して 3 次元を実現します。視覚効果。
コード分析:

コードをコピー コードは次のとおりです:

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+&#39;px&#39;; 
imgs[i].style.height=imgHeight+&#39;px&#39;; 
setImgPositionAndSize(imgs[i],0); 
} 
}
ログイン後にコピー

楕円の基本座標系を設定した後、画像の数に応じて画像の数を調整し、画像を楕円形に配置します。まず、画像間の間隔の角度を 2π/画像の数で求め、画像を均等に配置します。楕円軌道 このとき、すべての画像が楕円形を形成します。ここで画像の初期分布状態が得られます。次のタスクは、画像をこの軌道に沿って移動させることです。

コードをコピー コードは次のとおりです:

/* 设置图片位置和大小的匀速变化 */ 
var setImgPositionAndSize=function(img,path,direction){ 
direction=direction||&#39;CW&#39;; 
var dir=direction==&#39;CW&#39;?-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=&#39;position:absolute;left:&#39;+left+&#39;px;&#39; 
+&#39;top:&#39;+top+&#39;px;&#39; 
+&#39;width:&#39;+imgWidth*scale+&#39;px;&#39; 
+&#39;height:&#39;+imgHeight*scale+&#39;px;&#39; 
+&#39;z-index:&#39;+Math.round(scale*100); 
}
ログイン後にコピー

楕円の軌跡に従って画像を回転する方法回転角度を変えると?前の楕円方程式に戻って見てみましょう: () 処理する必要があるのは回転なので、x、y の処理を​​回転角度の処理に変換して、x、y 座標を表現できるようにしたいと考えています。 x =a*cosα、y=b*sinα となります。画像の X 座標は次のように表されます。 )、Y 軸は同じです。前述したように、画像のズーム サイズは画像の位置に基づいているため、拡大縮小率スケールの値は、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!=&#39;undefined&#39;)&&window.clearInterval(timeId); 
if(patternName===&#39;auto&#39;){//自动模式 可传入旋转方向:option.rotateDir 旋转速度:option.rotateSpeed 
var self=this; 
var direction=option.rotateDir||&#39;CW&#39;;//顺时针: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===&#39;hand&#39;){//手动模式,可传回调函数:option.onSelected 缓动模式:option.tween 
var onSelected=option.onSelected||util.emptyFunction; 
var tween=Tween[tween]||Tween[&#39;easeOut&#39;];//缓动模式默认为easeout 
removeImgsHandler(this.imgs); 
(typeof timeId!=&#39;undefined&#39;)&&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==&#39;Function&#39;||typeof func==&#39;Object&#39;){ 
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],&#39;click&#39;,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=&#39;ACW&#39;; 
angle=3*Math.PI/2-RC; 
} 
else{ 
dir=&#39;CW&#39;; 
Math.sin(RC)>=0?angle=Math.PI/2+RC:angle=RC-3*Math.PI/2; 
} 
(typeof timeId!=&#39;undefined&#39;)&&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==&#39;CW&#39;?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==&#39;hand&#39;){ 
onSelected=onSelected||util.emptyFunction; 
var tween=tween||Tween[&#39;easeOut&#39;]; 
if(typeof timeId!=&#39;undefined&#39;){ 
return; 
}else{ 
rotateAngle(this.imgs,con,&#39;ACW&#39;,tween,onSelected); 
} 
} 
}, 
/* 选择下一幅图片 */ 
nextPho:function(onSelected){ 
if(this.pattern==&#39;hand&#39;){ 
onSelected=onSelected||util.emptyFunction; 
var tween=tween||Tween[&#39;easeOut&#39;]; 
if(typeof timeId!=&#39;undefined&#39;){ 
return; 
}else{ 
rotateAngle(this.imgs,con,&#39;CW&#39;,tween,onSelected); 
} 
} 
},
ログイン後にコピー

  另外在手动模式下,提供选择上一张图片和下一张图片的接口,原理就是使所有图片的旋转角度为图片之间的夹角,上一张图片和下一张图片的旋转方向分别设置为逆时针和顺时针。

复制代码 代码如下:

var rp=new rotatePhos(&#39;container&#39;); 
rp.setPattern(&#39;auto&#39;,{rotateSpeed:10});//自动模式 旋转速度为10 
rp.setPattern(&#39;hand&#39;);//手动模式
ログイン後にコピー

  最后是调用方法初始化后需要设置旋转的模式。
  说了一大堆不知道说清楚了没有,这里提供所有源码,有兴趣的童鞋可以看看哈~
源代码:
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(&#39;hand&#39;);" checked="checked"/> 
自动模式:<input id="select" type="radio" name="sel" value="自动模式" onclick="rp.setPattern(&#39;auto&#39;);" /> 
</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+&#39;px&#39;; 
imgs[i].style.height=imgHeight+&#39;px&#39;; 
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=&#39;position:absolute;left:&#39;+left+&#39;px;&#39; 
+&#39;top:&#39;+top+&#39;px;&#39; 
+&#39;width:&#39;+imgWidth*scale+&#39;px;&#39; 
+&#39;height:&#39;+imgHeight*scale+&#39;px;&#39; 
+&#39;z-index:&#39;+Math.round(scale*100); 
} 
/* 设置图片位置和大小的匀速变化 */ 
var setImgPositionAndSize=function(img,path,direction){ 
direction=direction||&#39;CW&#39;; 
var dir=direction==&#39;CW&#39;?-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==&#39;CW&#39;?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=&#39;ACW&#39;; 
angle=3*Math.PI/2-RC; 
} 
else{ 
dir=&#39;CW&#39;; 
Math.sin(RC)>=0?angle=Math.PI/2+RC:angle=RC-3*Math.PI/2; 
} 
(typeof timeId!=&#39;undefined&#39;)&&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],&#39;click&#39;,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(&#39;hand&#39;);" type="radio" name="sel" value="手动模式" /> 自动模式:<input id="select" onclick="rp.setPattern(&#39;auto&#39;);" 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 + &#39;px&#39;; 
imgs[i].style.height = imgHeight + &#39;px&#39;; 
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 = &#39;position:absolute;left:&#39; + left + &#39;px;&#39; 
+ &#39;top:&#39; + top + &#39;px;&#39; 
+ &#39;width:&#39; + imgWidth * scale + &#39;px;&#39; 
+ &#39;height:&#39; + imgHeight * scale + &#39;px;&#39; 
+ &#39;cursor:pointer;&#39; 
+ &#39;z-index:&#39; + Math.round(scale * 100); 
} 
/* 设置图片位置和大小的匀速变化 */ 
var setImgPositionAndSize = function(img, path, direction) { 
direction = direction || &#39;CW&#39;; 
var dir = direction == &#39;CW&#39; ? -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 = &#39;position:absolute;left:&#39; + left + &#39;px;&#39; 
+ &#39;top:&#39; + top + &#39;px;&#39; 
+ &#39;width:&#39; + imgWidth * scale + &#39;px;&#39; 
+ &#39;height:&#39; + imgHeight * scale + &#39;px;&#39; 
+ &#39;z-index:&#39; + Math.round(scale * 100); 
} 
/* 旋转指定角度 */ 
var rotateAngle = function(imgs, angle, dir, tween, onSelected) { 
var duration = 1000; 
var startTime = (new Date()).getTime(); 
dir == &#39;CW&#39; ? 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 = &#39;ACW&#39;; 
angle = 3 * Math.PI / 2 - RC; 
} 
else { 
dir = &#39;CW&#39;; 
Math.sin(RC) >= 0 ? angle = Math.PI / 2 + RC : angle = RC - 3 * Math.PI / 2; 
} 
(typeof timeId != &#39;undefined&#39;) && 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], &#39;click&#39;, 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], &#39;click&#39;, 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.$$(&#39;img&#39;, 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 = &#39;relative&#39;; 
this.container.style.width = width + &#39;px&#39;; 
this.container.style.height = height + &#39;px&#39;; 
changeRotateWH.call(this, width, height); //改变容器尺寸后改变旋转轨迹 
}, 
/* 选择上一幅图片 */ 
prePho: function(onSelected) { 
if (this.pattern == &#39;hand&#39;) { 
onSelected = onSelected || util.emptyFunction; 
var tween = tween || Tween[&#39;easeOut&#39;]; 
if (typeof timeId != &#39;undefined&#39;) { 
return; 
} else { 
rotateAngle(this.imgs, con, &#39;ACW&#39;, tween, onSelected); 
} 
} 
}, 
/* 选择下一幅图片 */ 
nextPho: function(onSelected) { 
if (this.pattern == &#39;hand&#39;) { 
onSelected = onSelected || util.emptyFunction; 
var tween = tween || Tween[&#39;easeOut&#39;]; 
if (typeof timeId != &#39;undefined&#39;) { 
return; 
} else { 
rotateAngle(this.imgs, con, &#39;CW&#39;, tween, onSelected); 
} 
} 
}, 
/* 添加缓动模式 */ 
addTweenFunction: function(name, func) { 
if (typeof func == &#39;Function&#39; || typeof func == &#39;Object&#39;) { 
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 != &#39;undefined&#39;) && window.clearInterval(timeId); 
if (patternName === &#39;auto&#39;) {//自动模式 可传入旋转方向:option.rotateDir 旋转速度:option.rotateSpeed 
var self = this; 
var direction = option.rotateDir || &#39;CW&#39;; //顺时针: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 === &#39;hand&#39;) {//手动模式,可传回调函数:option.onSelected 缓动模式:option.tween 
var onSelected = option.onSelected || util.emptyFunction; 
var tween = Tween[tween] || Tween[&#39;easeOut&#39;]; //缓动模式默认为easeout 
removeImgsHandler(this.imgs); 
(typeof timeId != &#39;undefined&#39;) && window.clearInterval(timeId); 
timeId = undefined; 
bindHandlerForImgs(this.imgs, this.path, tween, onSelected); 
} 
} 
} 
})(); 
return rp; 
})(); 
var rp=new rotatePhos(&#39;container&#39;); 
//rp.setPattern(&#39;auto&#39;,{rotateSpeed:10}); 
rp.setPattern(&#39;hand&#39;); 
document.getElementById(&#39;pre&#39;).onclick=function(){rp.prePho();}; 
document.getElementById(&#39;next&#39;).onclick=function(){rp.nextPho();}; 
// ]]></script> 
</p>
ログイン後にコピー
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート