var
carousel =
new
Carousel({
wrap: document.getElementById(
"carousel"
),
urlArr: [
"img/1.jpg"
,
"img/2.jpg"
,
"img/3.jpg"
]
});
var
other =
new
Carousel({
wrap: document.getElementById(
"other"
),
urlArr: [
"img/4.jpg"
,
"img/5.jpg"
,
"img/6.jpg"
]
});
|
首先看一下如何使用这个组件,用到了font-awesome图标库,然后调用轮播图的css,最后是用户自己的css,用户必须设置容器id以及容器宽高,否则无法正常显示。生成轮播图时给构造函数传入容器元素,以及图片地址:
下边我们看下具体实现。首先是轮播图的构造函数:
function
Carousel(obj) {
this
.wrap = obj.wrap;
this
.wrapId = obj.wrap.id;
//容器的id
this
.wrapWidth =
this
.wrap.offsetWidth;
//容器宽
this
.imgNumber = obj.urlArr.length;
//图片数
this
.activePage = 0;
//轮播图当前页
this
.settimeID;
//定时器id
this
.init(obj.urlArr);
}
|
基本思路就是在构造函数里写入轮播图的实例属性,不同的轮播图具有不同的实例属性,将其共同拥有的方法写成原型属性,原型对象的基本结构如下所示:
Carousel.prototype = {
constructor: Carousel,
//构造函数指向原函数
init:
function
(urlArr){},
//构建DOM结构
bindEvent:
function
(){},
//绑定事件
pageActiveColor:
function
(){},
//绘制圆点
leftAngleclick:
function
(){},
//点击左箭头
rightAngleclick:
function
(){},
selectPage:
function
(selectNum){},
//点击圆点定位到指定图片
setTime:
function
(){},
//自动播放
clearTime:
function
(){}
//鼠标悬浮取消自动播放
}
|
建立dom结构的代码如下,根据容器的id生成后代dom节点的id以及class,然后在css中使用[attribute$=value]选择器对不同轮播图使用同样的样式。而在代码中也可以根据其容器id来区分不同轮播图中的类似元素。因为要支持轮播图宽度自适应,所以采用来百分比设置后代元素宽度。
init:
function
(urlArr) {
//创建dom结构
this
.wrap.style.position =
"relative"
;
this
.wrap.style.overflow =
"hidden"
;
this
.wrap.innerHTML =
'+
this
.wrapId +
'_pre" class="fa fa-angle-left fa-3x">+
this
.wrapId +
'_next" class="fa fa-angle-right fa-3x">
this
.wrapId +
'_page">
;
let container = document.getElementById(
this
.wrapId +
'_container'
);
let page = document.getElementById(
this
.wrapId +
"_page"
);
for
(let value of urlArr) {
//构建圆点
container.innerHTML +=
'
;
page.innerHTML +=
'
this
.wrapId +
'_pagination">'
;
}
container.style.width =
this
.imgNumber +
"00%"
;
container.style.left = 0;
for
(let value of document.getElementsByClassName(
this
.wrapId +
"_img-item"
)) {
value.style.width = 100 /
this
.imgNumber +
"%"
;
}
document.getElementsByClassName(
this
.wrapId +
"_pagination"
)[
this
.activePage].id =
this
.wrapId +
"_active"
;
this
.pageActiveColor();
this
.setTime();
this
.bindEvent();
}
|
创建的结构大体上如图下所示:#id代表用户定义的容器,生成一个#(id)_container的包裹元素,宽度是容器宽度的图片张数倍,.(id)_img-item[n]的宽度和高度都等同于容器,图片在各自的.(id)_img-item[n]里铺满。给容器定义属性position: relative,通过设置了绝对定位的#(id)_container的left值来实现轮播。
为左右箭头以及下边的小圆点添加事件,在鼠标移入轮播图时停止自动播放,移出时设置自动播放。需要注意的是addEventListener的第二个参数必须是bind了this后的函数。因为调用环境自带的函数会使this的绑定丢失,如果不清楚this的指向的话可以看这篇文章。
bindEvent:
function
() {
//绑定事件
let preAngle = document.getElementById(
this
.wrapId +
"_pre"
);
let nextAngle = document.getElementById(
this
.wrapId +
"_next"
);
let pageUl = document.getElementById(
this
.wrapId +
"_page"
);
let pages = pageUl.getElementsByClassName(
this
.wrapId +
"_pagination"
);
for
(let key = 0; key < pages.length; key++) {
pages[key].addEventListener(
"click"
,
this
.selectPage.bind(
this
, key));
console.log(key);
}
this
.wrap.addEventListener(
"mouseenter"
,
this
.clearTime.bind(
this
));
this
.wrap.addEventListener(
"mouseleave"
,
this
.setTime.bind(
this
));
preAngle.addEventListener(
"click"
,
this
.leftAngleclick.bind(
this
));
nextAngle.addEventListener(
"click"
,
this
.rightAngleclick.bind(
this
));
}
|
切换图片的基本思路就是改变实例属性中的当前页这个变量,然后根据这个变量的值对包裹元素进行定位,再使对应的小圆点变色。下边是点击左箭头触发的函数,判断如果处于边缘就跳到最后。点击右箭头和下边圆点的事件与之类似。
leftAngleclick:
function
() {
//点击左箭头
let container = document.getElementById(
this
.wrapId +
"_container"
);
if
(
this
.activePage == 0) {
//判断是否到边缘
this
.activePage =
this
.imgNumber - 1;
}
else
{
this
.activePage--;
}
container.style.left =
"-"
+
this
.activePage +
"00%"
;
this
.pageActiveColor();
}
|
最后给轮播图添加自动播放功能,即利用定时器每3秒触发一次右箭头的点击事件。将返回的定时器保存到实例属性中,以便在鼠标悬停的时候停止自动轮播。
setTime:
function
() {
//自动播放
let wrapId =
this
.wrapId;
//解决this绑定丢失
this
.settimeID = setInterval(
function
() {
document.getElementById(wrapId +
"_next"
).click();
} , 3000);
console.log(
"set"
);
},
clearTime:
function
() {
//鼠标悬浮取消自动播放
let theId =
this
.settimeID;
//解决this绑定丢失
console.log(
"clear"
);
clearInterval(theId);
}
|