【CSON原创】javascript图片滚动效果发布
功能说明:
在GMC实习的时候,写过一个图片滚动切换的控件,现在也发布一下。
1。支持点击左右按钮滚动图片。
2。支持点击右上角的选择按钮进行图片滚动。
支持IE 6 7 8 FireFox Chrome
效果预览:
实现原理:
把所有对象包含在单行,并且通过按钮的点击,控制单行的移动,实现图片滚动效果。
通过对数函数实现移动的先加速后减速效果。
代码分析:
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写在工具类中,具体如下:
for(var name in source){
destination[name]=source[name];
}
return destination;
}
这里由于传入的参数没有引用类型,所以工具类中的extend只实现了浅复制。
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后传入处理移动的函数。
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,该函数如下:
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来限定位移量。
{
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:
$: 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:
.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:
<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#