组件api说明
1、依赖move.js,组件前一定要引入move.js
2、轮播图需要有一个父级,这个父级一定要给一个id
默认参数:
this.settings={
'pic', //轮播图父级的id, 必需传的参数
autoplay:true, true为自动,false为不自动,默认为true
intervalTime:1000, 运动后停顿的时间,默认1s
loop:true, true为循环,false为不循环,默认为true
5,//图片总量
moveNum:1, (图片总量必须为运动数量的整倍数)
circle:true, true为显示,false为不显示,默认显示
moveWay:'opacity' opacity为透明度过渡,position为位置过渡
};
有了组件,可以更方便,引入组件后,只需要用户参入相应参数,就可以实现轮播图功能
下面是banner轮播图的代码:
//banner轮播图
var bannerPic=new Carousel();
bannerPic.init({
id:'bannerPic',
autoplay:true,
intervalTime:3000,
loop:true,
totalNum:5,
moveNum:1,
circle:true,
moveWay:'opacity'
});
;(function(window,undefined){
var Carousel=function(){
//配置参数
this.settings={
id:'pic', //轮播图父级的id, 必需传的参数
autoplay:true, //自动播放, true为自动,false为不自动,默认为true
intervalTime:1000, //间隔时间, 运动后停顿的时间,默认1s
loop:true, //循环播放, true为循环,false为不循环,默认为true
totalNum:5, //图片总量
moveNum:1, //单次运动的图片数量 (图片总量必须为运动数量的整倍数)
circle:true, //小圆点功能, true为显示,false为不显示,默认显示
moveWay:'opacity' //运动方式, opacity为透明度过渡,position为位置过渡
};
};
Carousel.prototype={
constructor:Carousel,//重新指向构造函数
init:function(opt){
var opt=opt||this.settings;//用户没有传参,就使用默认的
for (var attr in opt) {
this.settings[attr]=opt[attr];//用户参数覆盖默认参数
}
this.createDom();//调用函数
},
createDom:function(){//创建dom结构
var This=this;
this.box=document.getElementById(this.settings.id);
//创建上一个按钮
this.prevBtn=document.createElement("div");
this.prevBtn.className='prev';
this.prevBtn.innerHTML='<';
this.prevBtn.onclick=function(){
This.prev();
This.trigger('leftClick');
};
this.box.appendChild(this.prevBtn);//把创建的元素添加到父级box身上
//创建下一个按钮
this.nextBtn=document.createElement("div");
this.nextBtn.className='next';
this.nextBtn.innerHTML='>';
this.nextBtn.onclick=function(){
This.next();
This.trigger('rightClick');
};
this.box.appendChild(this.nextBtn);//把创建的元素添加到父级box身上
//创建圆点的父级
this.circleWrap=document.createElement("div");
this.circleWrap.className='circle';
//创建圆点
this.circles=[];//存圆点,方便后面修改圆点的class
for (var i=0;i<this.settings.totalNum/this.settings.moveNum;i++) {
var span=document.createElement("span");
span.index=i;
span.onclick=function(){
This.cn=this.index;
This[This.settings.moveWay+'Fn']();
};
this.circleWrap.appendChild(span);//添加圆点给父级
this.circles.push(span);
}
this.circles[0].className='active';
if(this.settings.circle){//如果需要圆点,才添加
this.box.appendChild(this.circleWrap);//添加圆点父级到box身上
}
this.moveInit();
},
//运动函数初始化
moveInit:function(){
this.cn=0;//当前索引
this.ln=0;//上一个索引
this.canClick=true;//是否可以再次点击
this.endNum=this.settings.totalNum/this.settings.moveNum; //非循环运动时,运动的停止条件
this.opacityItem=this.box.children[0].children; //需要运动透明度的元素,图片
this.positionItemWrap=this.box.children[0].children[0]; //需要运动位置元素的父级
this.positionItem=this.positionItemWrap.children; //需要运动位置的所有元素li
switch(this.settings.moveWay){
case 'opacity'://运动透明度,需要设置透明度与transition
for(var i=0;i<this.opacityItem.length;i++){
this.opacityItem[i].style.opacity=0;
this.opacityItem[i].style.transition='.3s opacity';
}
this.opacityItem[0].style.opacity=1;
break;
case 'position'://运动位置,需要设置父级的宽度
//注意一个元素的宽度一定要加上margin
var leftMargin=parseInt(getComputedStyle(this.positionItem[0]).marginLeft);
var rightMargin=parseInt(getComputedStyle(this.positionItem[0]).marginRight);
//一个运动元素的实际宽度
this.singleWidth=leftMargin+this.positionItem[0].offsetWidth+rightMargin;//找问题,要炸了offsetWidth没加
//如果内容需要循环,要复制一份内容
if(this.settings.loop){
this.positionItemWrap.innerHTML+=this.positionItemWrap.innerHTML;//找问题,要炸了innerHTML没加
}
//复制内容后才能计算宽度
this.positionItemWrap.style.width=this.singleWidth*this.positionItem.length+'px';
break;
}
if(this.settings.autoplay){
this.autoPlay();//this不能忘记!!!!
}
},
//透明度运动方式
opacityFn:function(){//选项卡原理
//左边到头,this.cn<0
if(this.cn<0){
if(this.settings.loop){
//循环播放
this.cn=this.endNum-1;
}else{
//非循环播放
this.cn=0;
this.canClick=true;//最后一张,或者第一张点击了,即使再次点击transitionend不会执行
}
}
//右边到头
if(this.cn>this.endNum-1){
if(this.settings.loop){
//循环播放
this.cn=0;
}else{
//非循环播放
this.cn=this.endNum-1;
this.canClick=true;
}
}
//清除上一个圆点和图片的初始样式
this.opacityItem[this.ln].style.opacity=0;
this.circles[this.ln].className='';
//当前
this.opacityItem[this.cn].style.opacity=1;
this.circles[this.cn].className='active';
var en=0;
var This=this;
this.opacityItem[this.cn].addEventListener('transitionend',function(){
en++;
if(en==1){
This.canClick=true;
This.ln=This.cn;
This.endFn();//运动完成触发的自定义事件
}
});
},
//位置运动方式
positionFn:function(){
//左边到头,this.cn<0
if(this.cn<0){
if(this.settings.loop){
//循环播放
/*
* 在这里需要做两件事情
* 1、先让运动的父级的位置到中间(复制后的图片),为了往右走不会出现空白
* 2、同时需要修改索引值(到了中间了,并不是停在那了,而是要运动出前一排,所以cn的值要减个1,为了就是能运动)
*/
this.positionItemWrap.style.left=-this.positionItemWrap.offsetWidth/2+'px';
this.cn=this.endNum-1;
}else{
//非循环播放
this.cn=0;
}
}
//右边到头
/*if(this.cn>this.endNum-1){
if(this.settings.loop){
//循环播放,这里不用做改变,需要在运动结束后做条件判断
}else{
//非循环播放
this.cn=this.endNum-1;
}
}*/
if(this.cn>this.endNum-1 && !this.settings.loop){
this.cn=this.endNum-1;
}
//当不循环播放的时候,没有圆点,需要修改圆点
if(!this.settings.loop){
//清除上一个圆点和图片的初始样式
this.circles[this.ln].className='';
//当前
this.circles[this.cn].className='active';
}
//运动
//left=一个元素的宽度*当前cn的值*一次运动的个数
var This=this;
move(this.positionItemWrap,{left:-this.cn*this.singleWidth*this.settings.moveNum},300,'linear',function(){
//当运动到复制后的图片时,让父级的left值变为0
if(This.cn==This.endNum){
this.style.left=0;
This.cn=0;
}
This.endFn();//运动完成触发的自定义事件
This.canClick=true;
This.ln=This.cn;
});
},
//上一个按钮点击功能
prev:function(){
if(!this.canClick){//图片运动的时候,不能点击按钮
return;
}
this.canClick=false;
this.cn--;
this[this.settings.moveWay+'Fn']();
},
//下一个按钮点击功能
next:function(){
if(!this.canClick){//图片运动的时候,不能点击按钮
return;
}
this.canClick=false;
this.cn++;
this[this.settings.moveWay+'Fn']();
},
//自动播放功能
autoPlay:function(){
var This=this;
this.timer=setInterval(function(){
This.next();
},this.settings.intervalTime);
//鼠标移入停止运动
this.box.onmouseenter=function(){
clearInterval(This.timer);
This.timer=null;
}
//鼠标移出继续运动
this.box.onmouseleave=function(){
This.autoPlay();
}
},
//添加自定义事件
on:function(type,listener){
this.events=this.events||{};//若用户第一次没有添加自定义事件为{},第二次添加的时候就是this.events
this.events[type]=this.events[type]||[];
this.events[type].push(listener);
},
//调用自定义事件触发器
trigger:function(type){//自定义事件触发器
//不是所有组件都有自定义事件,故需要判断
if(this.events&&this.events[type]){
for (var i=0;i<this.events[type].length;i++) {
this.events[type][i].call(this);
}
}
},
//运动完成后触发的自定义事件
endFn:function(){
//非循环的运动,才添加自定义事件
if(!this.settings.loop){
//左边到头
if(this.cn==0){
this.trigger('leftEnd');
}
//右边到头
if(this.cn==this.endNum-1){
this.trigger('rightEnd');
}
}
}
};
window.Carousel=Carousel;//把Carousel挂载到window上
})(window,undefined);