之前我們做了一個簡陋效果的輪播圖,但是他有很多BUG,所以這次我們來改進一下,
首先,就是各種功能的封裝,將輪播圖里的各種功能封裝分離,不但便于維護,還有助于我們理清思路,并且讓我們更加深刻的了解什么是面向?qū)ο?
在做一個輪播圖的時候會分為這幾個步驟:
1. 獲取元素,通過DOM獲取到HTML元素,記住,獲取到的元素是對象
2. 獲取元素的css屬性,通過獲取元素的css樣式來獲得它的初始參數(shù),獲取得到的css樣式同樣也是對象
3. 通過js操作css樣式從而使元素改變位置,輪播,最基礎(chǔ)的就是元素位置的改變,從而使其中圖片變換
4. 添加動畫效果,通過js添加的動畫效果擁有更好的兼容性和靈活性,
通過以上幾個步驟,是不是覺得輪播圖瞬間容易了不少?其實DOM都是這幾步:先獲取,再操作,將其中的功能分離出來逐個擊破,
1. 獲取元素:
獲取元素的方法有很多:
通過id獲取:document.getElementById();
通過標簽名獲取:document.getElementsByTagName();
通過類名獲取:document.getElementsByClassName();
這些方法各有優(yōu)缺點,我選擇了下面的這種方法:
document.querySelectorAll()
//獲取元素節(jié)點對象
//獲取到的是一個類數(shù)組函數(shù),所以使用時要進行遍歷
function $(selector){//css選擇器
return document.querySelectorAll(selector);
}
2. 獲取css樣式:為了更方便的使用,我選擇獲取內(nèi)聯(lián)或外部樣式,用以下方法:
getComputedStyle()是現(xiàn)在常用的方法,它的作用是一個元素的style屬性,注意,style屬性也是一個對象
這個函數(shù)在IE8中不兼容,所以對IE8需要使用currentStyle方法
為了方便,直接將其寫成一個兼容函數(shù)讓他自動判斷
//獲取一個元素的css內(nèi)聯(lián)或外部樣式
function getStyle(el,attr){//元素節(jié)點對象,樣式名
if (typeof getComputedStyle == "undefined") {
return el.currentStyle[attr];
}else{
return getComputedStyle(el,null)[attr];
}
}
3.操作樣式,添加動畫:這個是最復(fù)雜的功能,我在這里需配合著獲取css樣式的getStyle()函數(shù)使用
現(xiàn)在最新的設(shè)置js動畫的方法,不在用一個值疊加距離,而是通過動畫運動的時間和路程,直接將元素放在每一刻它應(yīng)該在的位置
得到起始位置b
得到運動次數(shù)d
設(shè)置當(dāng)前次數(shù)t
得到總路程c
結(jié)果就是每一刻元素應(yīng)該在c/d*t+b的位置上
這種方法計算得出的動畫效果更好,且規(guī)避了一些用距離疊加的方法產(chǎn)生的問題
//設(shè)置動畫效果
function animate(el,option,allTime,callback){//元素節(jié)點對象,要設(shè)置的樣式的對象集合,過渡時間,執(zhí)行完畢后要執(zhí)行的函數(shù)
//得到起始位置
var start = {};
for(var attr in option){
start[attr] = parseInt(getStyle(el,attr));
}
var d = parseInt(allTime/17);//得到運動次數(shù)
var t = 0;//得到當(dāng)前次數(shù)
clearInterval(el.time);
el.time = setInterval(function(){
t++;
for(var attr in option){
var b = start[attr];
var c = option[attr] - b;//得到總路程
if (t > d) {
clearInterval(el.time);
callback?callback():null;
}else{
el.style[attr] = c/d*t+b+"px";
}
}
},17)
}
這個功能不止可以移動元素,之前說過,js動畫的特點就是靈活,所以這個函數(shù)可以做很多事情,如:
改變位置:animate(obj,{left:400,top:300},300):將obj在0.3秒內(nèi)移動到left為400px,top為300px的位置
改變大小:animate(obj,{height:400},300):將obj的高度在0.3秒內(nèi)增加或減小到400px
以上三個功能都做好并理解之后,就可以思考怎樣做輪播圖了,
完成輪播圖:
看十遍不如做一遍,將相應(yīng)代碼復(fù)制到編輯器中試一下,了解各行代碼功能后再試著自己寫一遍看看
我設(shè)置的HTML頁面:
注意:類名和css樣式一定要一致,
<div class="box">
<div class="lise">
<div class="img"style="background: red">1</div>
<div class="img"style="background: purple;">2</div>
<div class="img"style="background: blue">3</div>
</div>
<div class="btn">
<button class="item bgcolor"></button>
<button class="item"></button>
<button class="item"></button>
</div>
<button class="btn1 onLeft">向左</button>
<button class="btn1 onRigth">向右</button>
</div>
我設(shè)置的內(nèi)聯(lián)css樣式:
注意:將其放在style標簽中或者放在外部引用
.box{
width: 400px;height: 200px;position: relative;
border: 2px solid #000;box-shadow: 0px 0px 5px red;
margin: 100px auto;
}
.lise{
width: 1200px;height: 100%;position: absolute;top: 0px;
}
.img{
width: 400px;height: 200px;float: left;
color: #fff;text-align: center;font-size: 50px;line-height: 200px;
}
.btn{
position: absolute;bottom: 10px;left: 50%;transform: translateX(-50%);
}
.item{
width: 15px;height: 15px;display: block;float: left;outline: none;
background: #fff;margin: 0px 10px;border-radius: 50%;
}
.bgcolor{
background: #999;
}
.btn1{
width: 40px;height: 100px;background: rgba(0,0,0,0.5);position: absolute;
color: #fff;top: 50%;transform: translateY(-50%);outline: none;
}
.onLeft{
left: 0px;
}
.onRigth{
right:0px;
}
用來設(shè)置輪播圖的JS代碼:
注意:JS代碼應(yīng)該寫在script標簽中,上面寫好的三個功能記得添加進來,如果寫在外部,記得引用進來,引用的script標簽一定要寫在輪播圖的script標簽前面
具體的各行代碼的介紹都在注釋里,為了簡化代碼所以將重復(fù)的代碼放在函數(shù)中調(diào)用,如果不明白可以將其重新放入函數(shù)調(diào)用的位置測試,
var item = $(".item"),box = $(".box"),lise = $(".lise"),onLeft = $(".onLeft"),onRight = $(".onRigth");
//自動輪播
var time = setInterval(next,3000);
box[0].onmouseover = function(){//鼠標進入
clearInterval(time);//關(guān)閉定時器
};
box[0].onmouseout = function(){//鼠標移出
time = setInterval(next,3000);//重新開啟定時器
};
//div的動畫
num = 0;//用來判斷是第幾張圖
onLeft[0].onclick = function () {//點擊向左
num = num<=0?2:--num;
move();//調(diào)用下面的move函數(shù)
};
onRight[0].onclick = function () {//點擊向右
num = num>=2?0:++num;
move();
};
for (var i = 0; i < item.length; i++) {//點擊小圓點
item[i].index = i;
item[i].onclick = function (){
num = this.index;//為了保證深色小圓點是當(dāng)前圖片,將下標給num
move();
};
}
function next(){
num = num>=2?0:++num;
move();
}
function move(){//將各事件中重復(fù)的代碼放在一個函數(shù)中以供調(diào)用
for(var j = 0;j<item.length;j++){//用類名改變小圓點的顏色,使對應(yīng)圖片的小圓點變色
item[j].className = "item";
}
item[num].className = "item bgcolor";
animate(lise[0],{left:num*-400},300)//執(zhí)行的動畫
}