【CSON原创】javascript图片滚动效果发布

功能说明:

在GMC实习的时候,写过一个图片滚动切换的控件,现在也发布一下。

1。支持点击左右按钮滚动图片。

2。支持点击右上角的选择按钮进行图片滚动。

支持IE 6 7 8 FireFox Chrome

效果预览:

 
 

实现原理:

把所有对象包含在单行,并且通过按钮的点击,控制单行的移动,实现图片滚动效果。

通过对数函数实现移动的先加速后减速效果。

代码分析:

var defaults = {
changerId:
'phos_changer', //控件id
containerId: 'phos_container', //图片包含块id
bodyId: 'boxDiv2', //包含块外div的id
select_btn_Id:'select', //选择按钮前缀
bodyWidth: 500, //显示区域宽度
left_btn_Id: 'left_btn', //左按钮id
right_btn_Id: 'right_btn', //右按钮id
movePath: 300, //切换速度
groupCount: 5, //每次显示个数
btnClass: 'btn', //左右按钮类
selectorContainerId:'select_btns_area', //选择按钮的容器id
left_btn_disble_Class: 'left_btn_disable', //左按钮禁用时样式类
right_btn_disble_Class: 'right_btn_disable', //右按钮禁用时样式类
select_btn_Class:'select_btn', //选择按钮样式类
left_btn_Class:'left_btn', //左按钮样式类
right_btn_Class:'right_btn', //右按钮样式类
left_btn_over_Class:'left_btn_over', //左按钮鼠标移上去时样式类
right_btn_over_Class:'right_btn_over', //右按钮鼠标移上去时样式类
select_btn_selected_Class:'select_btn_selected'//选择按钮被选择后样式类
};
var opts=util.extend(defaults,option);

首先定义默认值对象,里面包含所有参数的默认值,包括左右按钮ID,按钮不同状态下使用的样式class,每次显示对象的数量等,并且下面使用extend把用户传入的参数对象与默认对象结合,形成最终的参数对象,extend写在工具类中,具体如下:

extend:function(destination,source){
for(var name in source){
destination[name]
=source[name];

}
return destination;
}

这里由于传入的参数没有引用类型,所以工具类中的extend只实现了浅复制。

set_EventsHandler_for_selectors:function(obj){
util.addEventHandler(obj.selectorContainer,
'click',function(eve){
eve
=eve||window.event;
var target=eve.target||eve.srcElement;
if(target!=obj.currentSelector){
var targetIndex=target.id.charAt(target.id.length-1);
var currentIndex=obj.currentSelector.id.charAt(obj.currentSelector.id.length-1);
var len=targetIndex-currentIndex;
if(len>0){
for(var t=0;t<len;t++){

len
>1?obj._moveLeft(obj,obj.movePath+300)():obj._moveLeft(obj)();

}
}
else{
for(var t=0;t<-len;t++){

len
<-1?obj._moveRight(obj,obj.movePath+300)():obj._moveRight(obj)();

}
}

}


});

},

为右上角的选择按钮绑定事件处理程序,当按钮跨度为2(例如有第一个选择按钮跳到第三个选择按钮时),增大滚动速度,原速度(movePath)增加300后传入处理移动的函数。

_moveLeft:function(obj,movePath) {
if(!movePath)movePath=obj.movePath;
returnfunction(){
if (obj.isLeft) {
if(obj.selectIndex<obj.selectorArray.length)
{
obj.selectorArray[obj.selectIndex].className
=obj.select_btn_Class;
obj.selectIndex
+=1;
obj.ori_left
= parseInt(util.getComputedStyle(obj.phos_container).left);
obj.selectorArray[obj.selectIndex].className
=obj.select_btn_Class+''+obj.select_btn_selected_Class; }
obj.currentLeft
=obj. currentLeft -obj.moveLength;
obj.isRight
=false;
obj._lMove(obj,movePath);

}
if (obj.currentLeft <=-(obj.container_length - obj.moveLength)) {

obj.right_btn.className
= obj.btnClass+''+obj.right_btn_Class +''+ obj.right_btn_disble_Class;

obj.isLeft
=false;
}
}

},

移动函数有向左移动和向右移动两个,由于两者原理相似,因此这里只分析向左移动函数。这里由于需要向事件处理程序传递参数,所以使用了闭包的方法,返回一个没有参数的function。

函数首先判断isLeft是否为true,isLeft是控制对象是否能向左滚动的一个属性,当为false时,意味着已经滚动到最后,不能继续滚动,此时不能调用“原子”的向左滚动函数_lMove,该函数如下:

_lMove:function(obj,movePath) {

if (parseInt(util.getComputedStyle(obj.phos_container).left) > obj.currentLeft) {

obj.path
+=1;

obj.phos_container.style.left
=Math.max(obj.currentLeft, obj.ori_left-Math.log(obj.path)/Math.log(5)*movePath) + 'px';
window.setTimeout(arguments.callee, 50,obj,movePath);
}
else {
obj.path
=0;

obj.isRight
=true;
obj.left_btn.className
= obj.btnClass+''+obj.left_btn_Class;
obj.getCurrentSelector();
}

},

这个就是前面所说的“原子”向左移动的函数,该函数通过定时器递归调用。所谓“原子”,就是每次该函数调用时只向左移动一个单位的位移,该单位的位移使用对数函数计算: 

单位位移=obj.ori_left-Math.log(obj.path)/Math.log(5)*movePath

利用对数函数曲线,可以实现先加速后减速的效果。并且需要注意的是由于每次移动固定的位移,所以必须保证移动后的位移小于等于极限的位移,因此需要用Math.max来限定位移量。

new phos_changer(
{
changerId:
'phos_changer1',
containerId:
'phos_container1',
selectorContainerId:
'select_btns_area1',
bodyId:
'boxDiv1',
select_btn_Id:
'select',
left_btn_Id:
'left_btn1',
right_btn_Id:
'right_btn1'
});

最后是调用的方法,传入一个对象,里面包含需要个性化的参数,实现对控件的初始化。

完整demo代码:

js: 

View Code
var util = {
$:
function(sId) { return document.getElementById(sId); },
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;
}


}

var _st = window.setTimeout;
window.setTimeout
=function(fRef, mDelay) {
if(typeof fRef =='function'){
var argu = Array.prototype.slice.call(arguments,2);
var f = (function(){ fRef.apply(null, argu); });
return _st(f, mDelay);
}
return _st(fRef,mDelay);
}
// ]]></script>
<script type="text/javascript">// <![CDATA[
var phos_changer =function(option){
this._init(option);
}

phos_changer.prototype
={
_init:
function(option){

var defaults = {
changerId:
'phos_changer', //控件id
containerId: 'phos_container', //图片包含块id
bodyId: 'boxDiv2', //包含块外div的id
select_btn_Id:'select', //选择按钮前缀
bodyWidth: 500, //显示区域宽度
left_btn_Id: 'left_btn', //左按钮id
right_btn_Id: 'right_btn', //右按钮id
movePath: 300, //切换速度
groupCount: 5, //每次显示个数
btnClass: 'btn', //左右按钮类
selectorContainerId:'select_btns_area', //选择按钮的容器id
left_btn_disble_Class: 'left_btn_disable', //左按钮禁用时样式类
right_btn_disble_Class: 'right_btn_disable', //右按钮禁用时样式类
select_btn_Class:'select_btn', //选择按钮样式类
left_btn_Class:'left_btn', //左按钮样式类
right_btn_Class:'right_btn', //右按钮样式类
left_btn_over_Class:'left_btn_over', //左按钮鼠标移上去时样式类
right_btn_over_Class:'right_btn_over', //右按钮鼠标移上去时样式类
select_btn_selected_Class:'select_btn_selected'//选择按钮被选择后样式类
};
var opts=util.extend(defaults,option);


this.phos_changer = util.$(opts.changerId);
this.phos_container = util.$(opts.containerId);
this.phos_body = util.$(opts.bodyId);
this.left_btn = util.$(opts.left_btn_Id);
this.right_btn = util.$(opts.right_btn_Id);
this.selectorContainer=util.$(opts.selectorContainerId);
this.select_btn_Class=opts.select_btn_Class;
this.selectorArray= util.getElementsByClassName(this.select_btn_Class,this.selectorContainer);
this.ori_left=this.currentLeft = parseInt(util.getComputedStyle(this.phos_container).left);
this.memberWidth =(this.phos_container.getElementsByTagName('li')[0]).clientWidth;
this.count =this.phos_container.getElementsByTagName('li').length;
this.isLeft =true;
this.isRight =false;
this.selectIndex=0;
this.movePath=opts.movePath;
this.select_btn_Id=opts.select_btn_Id;
this.groupCount;
this.btnClass=opts.btnClass;
this.left_btn_disble_Class=opts.left_btn_disble_Class;
this.right_btn_disble_Class=opts.right_btn_disble_Class;
this.left_btn.className = opts.btnClass +''+opts.left_btn_Class+''+ opts.left_btn_disble_Class;
this.left_btn_Class=opts.left_btn_Class;
this.right_btn_Class=opts.right_btn_Class;
this.left_btn_over_Class=opts.left_btn_over_Class;
this.right_btn_over_Class=opts.right_btn_over_Class;
this.select_btn_selected_Class=opts.select_btn_selected_Class;
this.path=0;

this.selectorArray[0].className=this.select_btn_Class+''+this.select_btn_selected_Class;

this.phos_body.style.width = opts.bodyWidth +'px';
this.groupCount =opts.groupCount;

this.moveLength =this.memberWidth *this.groupCount;
this.phos_body.style.width =this.moveLength +'px';

this.container_length =this. memberWidth *this. count;
this.phos_container.style.width =this.container_length +'px';

util.addEventHandler(
this.left_btn, 'click', this._moveRight(this));
util.addEventHandler(
this.right_btn, 'click', this._moveLeft(this));
this.getCurrentSelector();
this.set_EventsHandler_for_selectors(this);
this._setBtnState();




},
/* 为选择按钮设置事件处理程序 */
set_EventsHandler_for_selectors:
function(obj){
util.addEventHandler(obj.selectorContainer,
'click',function(eve){
eve
=eve||window.event;
var target=eve.target||eve.srcElement;
if(target!=obj.currentSelector){
var targetIndex=target.id.charAt(target.id.length-1);
var currentIndex=obj.currentSelector.id.charAt(obj.currentSelector.id.length-1);
var len=targetIndex-currentIndex;
if(len>0){
for(var t=0;t<len;t++){

len
>1?obj._moveLeft(obj,obj.movePath+300)():obj._moveLeft(obj)();//跨度大的切换提高切换速度

}
}
else{
for(var t=0;t<-len;t++){

len
<-1?obj._moveRight(obj,obj.movePath+300)():obj._moveRight(obj)();

}
}

}


});

},
/* 获得当前被选择的选择按钮 */
getCurrentSelector:
function(){
for(var i=0;i<this.selectorArray.length;i++){
if( this.selectorArray[i].className==this.select_btn_Class+''+this.select_btn_selected_Class){

this.currentSelector=this.selectorArray[i];
break;
}

}

},
/* 左移动原子方法 */
_lMove:
function(obj,movePath) {

if (parseInt(util.getComputedStyle(obj.phos_container).left) > obj.currentLeft) {

obj.path
+=1;

obj.phos_container.style.left
= Math.max(obj.currentLeft, obj.ori_left - Math.log(obj.path) / Math.log(5) * movePath) +'px'; //对数函数实现先加速再减速效果
window.setTimeout(arguments.callee, 50,obj,movePath);
}
else {
obj.path
=0;

obj.isRight
=true;
obj.left_btn.className
= obj.btnClass+''+obj.left_btn_Class;
obj.getCurrentSelector();
}

},

/* 右移动原子方法 */
_rMove:
function(obj,movePath) {
if (parseInt(util.getComputedStyle(obj.phos_container).left) < obj.currentLeft) {
obj.path
+=1;

obj.phos_container.style.left
=Math.min(obj.currentLeft,obj.ori_left + Math.log(obj.path)/Math.log(5)*movePath )+ 'px';//对数函数实现先加速再减速效果
window.setTimeout(arguments.callee, 50,obj,movePath);
}
else {
obj.path
=0;
obj.isLeft
=true;
obj.right_btn.className
= obj.btnClass+''+obj.right_btn_Class;
obj.getCurrentSelector();

}

},
/* 左移动方法 */
_moveLeft:
function(obj,movePath) {
if(!movePath)movePath=obj.movePath;
returnfunction(){
if (obj.isLeft) {
if(obj.selectIndex<obj.selectorArray.length)
{
obj.selectorArray[obj.selectIndex].className
=obj.select_btn_Class;
obj.selectIndex
+=1;
obj.ori_left
= parseInt(util.getComputedStyle(obj.phos_container).left);
obj.selectorArray[obj.selectIndex].className
=obj.select_btn_Class+''+obj.select_btn_selected_Class; }
obj.currentLeft
=obj. currentLeft -obj.moveLength;
obj.isRight
=false;
obj._lMove(obj,movePath);

}
if (obj.currentLeft <=-(obj.container_length - obj.moveLength)) {

obj.right_btn.className
= obj.btnClass+''+obj.right_btn_Class +''+ obj.right_btn_disble_Class;

obj.isLeft
=false;
}
}

},
/* 右移动方法 */
_moveRight:
function(obj,movePath) {
if(!movePath)movePath=obj.movePath;
returnfunction(){
if (obj.isRight) {

if(obj.selectIndex>0)
{
obj.selectorArray[obj.selectIndex].className
=obj.select_btn_Class;
obj.selectIndex
-=1;
obj.selectorArray[obj.selectIndex].className
=obj.select_btn_Class+''+obj.select_btn_selected_Class; }

obj.currentLeft
= obj.currentLeft + obj.moveLength;
obj.ori_left
= parseInt(util.getComputedStyle(obj.phos_container).left);
obj.isLeft
=false;
obj._rMove(obj,movePath);


}
if ( obj.currentLeft >=0) {

obj.left_btn.className
= obj.btnClass +''+obj.left_btn_Class +''+obj.left_btn_disble_Class;
obj.isRight
=false;
}
}
},
/* 改变鼠标移上按钮时按钮状态 */
_overStateChange:
function(btn,obj,dir){

returnfunction(){
var className;
dir
=='left'?className=obj.left_btn_Class+''+obj.left_btn_over_Class:className=obj.right_btn_Class+''+obj.right_btn_over_Class;
btn.className
=obj.btnClass+''+className;

}


},
/* 设置按钮的手型效果 */
_setBtnState:
function(){

for(var i=0;i<this.selectorArray.length;i++){
this.selectorArray[i].style.cursor='pointer';

}
this.left_btn.style.cursor=this.right_btn.style.cursor='pointer';


}












}
/* 初始化调用 */
new phos_changer(
{
changerId:
'phos_changer1',
containerId:
'phos_container1',
selectorContainerId:
'select_btns_area1',
bodyId:
'boxDiv1',
select_btn_Id:
'select',
left_btn_Id:
'left_btn1',
right_btn_Id:
'right_btn1'
});

CSS:

View Code
*{margin:0; padding:0}
.phos_changer
{width:650px; position:relative; height:200px;}
.productCol
{ overflow:hidden;height:100px; width:500px; position:absolute; left:50%; margin-left:-250px; top:30px;}
.phos_container
{height:100%; position:absolute; left:0; top:0;}
.btn
{width:45px; height:45px; position:absolute;}
.left_btn
{ left:20px; top:60px; z-index:100; background-image:url(http://images.cnblogs.com/cnblogs_com/Cson/290336/r_left-btn-over.png); background-repeat:no-repeat;}
.right_btn
{ right:20px; top:60px; z-index:100; background-image:url(http://images.cnblogs.com/cnblogs_com/Cson/290336/r_right-btn-over.png); background-repeat:no-repeat;}
.left_btn_over
{background-image:url(http://images.cnblogs.com/cnblogs_com/Cson/290336/r_left-btn-over.png);}
.right_btn_over
{background-image:url(http://images.cnblogs.com/cnblogs_com/Cson/290336/r_right-btn-over.png);}
.left_btn_disable
{background-image:url(http://images.cnblogs.com/cnblogs_com/Cson/290336/r_left-btn.png);}
.right_btn_disable
{background-image:url(http://images.cnblogs.com/cnblogs_com/Cson/290336/r_right-btn.png);}

.select_btns_area
{position:absolute; top:0; right:50px;}
.select_btn
{width:15px; height:15px; background-image:url(http://images.cnblogs.com/cnblogs_com/Cson/290336/r_pageBtn-up.png); background-repeat:no-repeat; float:left; margin-left:10px; display:inline;}

.select_btn_selected
{background-image:url(http://images.cnblogs.com/cnblogs_com/Cson/290336/r_pageBtn-select.png); background-repeat:no-repeat;}
.photo_container
{ width:100px; height:100px; background-color:Red; float:left;}

HTML:

View Code
<ul id="phos_changer1" class="phos_changer" style="list-style: none;">
<div id="select_btns_area1" class="select_btns_area">
<div id="select0" class="select_btn"></div>
<div id="select1" class="select_btn"></div>
<div id="select2" class="select_btn"></div>
</div>
<div id="left_btn1" class="btn left_btn"></div>
<div id="boxDiv1" class="productCol">
<div id="phos_container1" class="phos_container">
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_z.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_3.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_2a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_3a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_4a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_5a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_6a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_7a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_8a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_9a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_10a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_12a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_13a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_14a.jpg" style="width: 100%; height: 100%;"/></li>
<li class="photo_container"><img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_15a.jpg" style="width: 100%; height: 100%;"/></li>
</div>
</div>
<div id="right_btn1" class="btn right_btn"></div>
</ul>

  

欢迎转载,请标明出处:http://www.cnblogs.com/Cson/archive/2011/03/30/2000075.html#

posted @ 2011-03-30 16:45  Cson  阅读(2063)  评论(7编辑  收藏  举报