本文首發(fā)于我的博客,這是我的github,歡迎star。
這是一個(gè)輪播圖組件,你可以直接下載使用,這里是代碼地址,需要傳入容器的id
和圖片地址,支持Internet Explorer 10+
、Firefox
、Opera
和Chrome
等現(xiàn)代瀏覽器。
之前寫一些功能或是特效都是寫在一個(gè)個(gè)函數(shù)里,可能因?yàn)槲沂怯?code>c語(yǔ)言入門編程,所以更傾向于面向過(guò)程的編程方式,沒(méi)有想過(guò)將一個(gè)模塊抽象成為對(duì)象,做成組件。但是由于嘗到了重復(fù)造輪子之苦。我決定將不可復(fù)用的代碼做成組件,提高編程效率。以下就是我做輪播圖組件的全部過(guò)程,由于是第一次寫組件,如果有哪里思維不對(duì),或?qū)懙姆绞接袉?wèn)題,還希望不吝賜教,共同學(xué)習(xí)。
首先看一下如何使用這個(gè)組件,用到了font-awesome
圖標(biāo)庫(kù),然后調(diào)用輪播圖的css
,最后是用戶自己的css
,用戶必須設(shè)置容器id
以及容器寬高,否則無(wú)法正常顯示。生成輪播圖時(shí)給構(gòu)造函數(shù)傳入容器元素,以及圖片地址:
<head>
<meta charset="UTF-8">
<title>輪播圖</title>
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/carousel.css">
<link rel="stylesheet" href="css/user-index.css">
</head>
<body>
<div id="carousel"></div>
<div id="other"></div>
<script src="js/carousel.js"></script>
<script>
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"]
});
</script>
</body>
下邊我們看下具體實(shí)現(xiàn)。首先是輪播圖的構(gòu)造函數(shù):
function Carousel(obj) {
this.wrap = obj.wrap;
this.wrapId = obj.wrap.id; //容器的id
this.wrapWidth = this.wrap.offsetWidth; //容器寬
this.imgNumber = obj.urlArr.length; //圖片數(shù)
this.activePage = 0; //輪播圖當(dāng)前頁(yè)
this.settimeID; //定時(shí)器id
this.init(obj.urlArr);
}
基本思路就是在構(gòu)造函數(shù)里寫入輪播圖的實(shí)例屬性,不同的輪播圖具有不同的實(shí)例屬性,將其共同擁有的方法寫成原型屬性,完整代碼請(qǐng)到github上查看,喜歡的可以順手給個(gè)星。原型對(duì)象的基本結(jié)構(gòu)如下所示:
Carousel.prototype = {
constructor: Carousel, //構(gòu)造函數(shù)指向原函數(shù)
init: function(urlArr){}, //構(gòu)建DOM結(jié)構(gòu)
bindEvent: function(){}, //綁定事件
pageActiveColor: function(){}, //繪制圓點(diǎn)
leftAngleclick: function(){}, //點(diǎn)擊左箭頭
rightAngleclick: function(){},
selectPage: function(selectNum){}, //點(diǎn)擊圓點(diǎn)定位到指定圖片
setTime: function(){}, //自動(dòng)播放
clearTime: function(){} //鼠標(biāo)懸浮取消自動(dòng)播放
}
建立dom
結(jié)構(gòu)的代碼如下,根據(jù)容器的id
生成后代dom
節(jié)點(diǎn)的id
以及class
,然后在css
中使用[attribute$=value]
選擇器對(duì)不同輪播圖使用同樣的樣式。而在代碼中也可以根據(jù)其容器id
來(lái)區(qū)分不同輪播圖中的類似元素。因?yàn)橐С州啿D寬度自適應(yīng),所以采用來(lái)百分比設(shè)置后代元素寬度。
init: function(urlArr) { //創(chuàng)建dom結(jié)構(gòu)
this.wrap.style.position = "relative";
this.wrap.style.overflow = "hidden";
this.wrap.innerHTML = '<span id="' + this.wrapId + '_pre" class="fa fa-angle-left fa-3x"></span><span id="' + this.wrapId + '_next" class="fa fa-angle-right fa-3x"></span><ul id="' + this.wrapId + '_page"></ul><div id="' + this.wrapId + '_container"></div>';
let container = document.getElementById(this.wrapId + '_container');
let page = document.getElementById(this.wrapId + "_page");
for (let value of urlArr) { //構(gòu)建圓點(diǎn)
container.innerHTML += '<div class="' + this.wrapId + '_img-item"></div>';
page.innerHTML += '<li class="' + this.wrapId + '_pagination"></li>';
}
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();
}
創(chuàng)建的結(jié)構(gòu)大體上如圖下所示:#id
代表用戶定義的容器,生成一個(gè)#(id)_container
的包裹元素,寬度是容器寬度的圖片張數(shù)倍,.(id)_img-item[n]
的寬度和高度都等同于容器,圖片在各自的.(id)_img-item[n]
里鋪滿。給容器定義屬性position: relative
,通過(guò)設(shè)置了絕對(duì)定位的#(id)_container
的left
值來(lái)實(shí)現(xiàn)輪播。
為左右箭頭以及下邊的小圓點(diǎn)添加事件,在鼠標(biāo)移入輪播圖時(shí)停止自動(dòng)播放,移出時(shí)設(shè)置自動(dòng)播放。需要注意的是addEventListener
的第二個(gè)參數(shù)必須是bind
了this
后的函數(shù)。因?yàn)檎{(diào)用環(huán)境自帶的函數(shù)會(huì)使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));
}
切換圖片的基本思路就是改變實(shí)例屬性中的當(dāng)前頁(yè)這個(gè)變量,然后根據(jù)這個(gè)變量的值對(duì)包裹元素進(jìn)行定位,再使對(duì)應(yīng)的小圓點(diǎn)變色。下邊是點(diǎn)擊左箭頭觸發(fā)的函數(shù),判斷如果處于邊緣就跳到最后。點(diǎn)擊右箭頭和下邊圓點(diǎn)的事件與之類似。
leftAngleclick: function() { //點(diǎn)擊左箭頭
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();
}
最后給輪播圖添加自動(dòng)播放功能,即利用定時(shí)器每3
秒觸發(fā)一次右箭頭的點(diǎn)擊事件。將返回的定時(shí)器保存到實(shí)例屬性中,以便在鼠標(biāo)懸停的時(shí)候停止自動(dòng)輪播。
setTime: function() { //自動(dòng)播放
let wrapId = this.wrapId; //解決this綁定丟失
this.settimeID = setInterval(function() {
document.getElementById(wrapId + "_next").click();
} , 3000);
console.log("set");
},
clearTime: function() { //鼠標(biāo)懸浮取消自動(dòng)播放
let theId = this.settimeID; //解決this綁定丟失
console.log("clear");
clearInterval(theId);
}
到這輪播圖組件就算寫好了,這可以讓我們少寫很多代碼,而且可以在一個(gè)頁(yè)面中多次使用,不會(huì)污染到全局變量。缺陷在于這時(shí)的輪播圖還不能支持10
張以上的圖片,因?yàn)榭紤]到這種需求并不是很多,就沒(méi)有寫10
張以上的判斷條件,有需要時(shí)可以自行添加。可以點(diǎn)擊這里預(yù)覽最終效果,如果對(duì)于這篇博客有什么建議或想法,歡迎到博客下方留言。