基於原生javascript的圖片輪播domo

如今不少javascript的插件均可以實現圖片輪播的功能,這篇文章,主要是經過這個domo來解析javascript圖片輪播的原理。javascript

老規矩,先上代碼。至於代碼中的圖片,隨便找三張便可,最核心的仍是理解其思想。css

html:html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>滾動圖</title>
		<link rel="stylesheet" type="text/css" href="css/scroll.css"/>
	</head>
	<body>
		<div id="wrapper">
			<div id="box">
				<img src="img/banner0.png"/>
				<img src="img/banner1.png"/>
				<img src="img/banner2.png"/>
			</div>
			<div id="pointer">
				<span class="active"></span>
				<span></span>
				<span></span>
			</div>
		</div>
		<script src="js/scroll.js" type="text/javascript" charset="utf-8"></script>
	</body>
</html>


css:

*{
	margin: 0;
	padding: 0;
}
#wrapper{
	position: relative;
	width: 1200px;
	margin: 50px auto;
	overflow: hidden;
}
#pointer{
	clear: both;
	position: absolute;
	right: 500px;
	bottom: 15px;
	width: 180px;
	height: 2px;
}
#pointer span{
	display: block;
	box-sizing: border-box;
	float: left;
	width: 50px;
	height: 1.5px;
	margin-right: 10px;
	border-radius: .5px;
	background: #fff;
	opacity: .5;
	-webkit-opacity: .5;
	-moz-opacity: .5;
	filter:alpha(opacity=50);
}
#pointer .active{
	opacity: .8;
	-webkit-opacity: .8;
	-moz-opacity: .8;
	filter:alpha(opacity=80);
}
#box{
	position: relative;
	width: 3600px;
	clear: both;
}
img{
	display: block;
	float: left;
	width: 1200px;
	height: 337px;
}


javascript:

window.onload = function(){
	//獲取裝圖片的盒子
	var box = document.getElementById('box');
	//獲取裝頁碼的盒子
	var pointer = document.getElementById('pointer');
	//獲取盒子中的全部圖片
	var imglist = box.getElementsByTagName('img')
	//獲取盒子中的全部頁碼
	var pointerList = pointer.getElementsByTagName('span');
	//圖片的寬度,正負用於左右的循環
	var n = -1200;
	//增長一倍的圖片用於循環
	box.innerHTML = box.innerHTML+box.innerHTML;
	//設置盒子的寬
	box.style.width = imglist[0].offsetWidth*imglist.length+"px";
	var timer = null;
	timer = setInterval(function(){
		scroll(box,n,pointerList);
	},3000);
	box.onmouseover = function(){
		clearInterval(timer);
	}
	pointer.onmouseover = function(){
		clearInterval(timer);
	}
	box.onmouseout = function(){
		timer = setInterval(function (){
//			console.log(new Date());
			scroll(box,n,pointerList);
		},3000);
	}
	//設置頁碼的點擊事件
	for(var i=0;i<pointerList.length;i++){
		pointerList[i].index=i;//設置一個參數,用下面調用某個頁碼
		//若是不設置參數,在調用頁碼的時候會直接調用最後一個,由於咱們使用了循環
		pointerList[i].onclick=function (){
			for(var j=0;j<pointerList.length;j++){
				pointerList[j].className='';//清空激活的class
			}
			move(box,n*(this.index));//移動圖片
			this.className='active';//激活點擊的頁碼
		}
	}
	
}
/**
 * 循環滾動函數
 * @param {Object} box
 * @param {Object} n
 */
function scroll(box,n,page){
	//判斷是否到達臨界點,即box的中間部分
	if(box.offsetLeft<=-box.offsetWidth/2){
		box.style.left = "0px";//從新從頭開始
		console.log('0');
	}
	if(box.offsetLeft%n!=0){
		//由於在咱們切換瀏覽器標籤頁或者切換去其餘軟件界面的時候,
		//會影響到setInterval,有時候setInterval會增長好幾秒,在這裏咱們必須加一個判斷
		//只有當它走完了一個整個的圖片寬度時,咱們才進行下一次滾動。
	}
	else{
		pageScroll(box,n,page);
		move(box,n+box.offsetLeft);
	}
}
/**
 * 滾動頁碼函數
 * @param {Object} box
 * @param {Object} n
 * @param {Object} page
 */
function pageScroll(box,n,page){
	//直接經過圖片盒子的定位判斷頁碼值,可是此時的頁碼值是滾動以前的,因此後面的值要+1使用
	var index = Math.abs(box.offsetLeft/n);
	console.log(index);
	for(var i=0;i<page.length;i++){
		page[i].className='';
	}
	//判斷是否是最後一頁,是最後一頁的話+1要變成0;
	if(index<page.length-1){
		page[index+1].className='active';
	}
	else{
		page[0].className='active';
	}
}

/**
 * 變速移動
 * @param {Object} ele
 * @param {Object} target
 */
function move(ele,target){ 
	clearInterval(ele.timer);
	console.log(new Date());
    ele.timer = setInterval(function () {
	    var step = (target-ele.offsetLeft)/10;
	    step = step>0?Math.ceil(step):Math.floor(step);
	    if(target==ele.offsetLeft){
	        console.log(new Date());
	        clearInterval(ele.timer);
	    }
	    else{
	    	ele.style.left = ele.offsetLeft + step + "px";
	    }
	},30);
}

html和css部分依舊比較簡單,直接跳過。javascript部分的代碼註釋寫的也比較詳細,下面主要講解邏輯部分。

圖片滾動的原理是利用setInterval函數進行背景圖片的不斷循環。爲了不圖片循環的過程當中出現間斷,首先是在javascript中進行圖片的複製(增長一倍),而後當到達臨界點時,瞬間將圖片移動到初始的位置,而後開始下一輪循環。java

在這個domo中,主要包含四個函數:web

一、外層控制間隔時間的函數。這個比較容易理解,經過setInterval函數每隔幾秒循環執行一次圖片滾動的函數。瀏覽器

二、中間層滾動函數。判斷圖片盒子是否到達臨界點,判斷當前狀態是否符合進入下一次滾動(這個條件主要是爲了防止切換界面對setInterval函數的影響,具體緣由在最後)。app

三、中間層頁碼滾動函數。基本沒有難點,主要是理解頁碼爲何+1便可。dom

四、圖片滾動函數。這個在以前寫過的一篇文章有詳細講解,再也不贅述。 javascript勻速動畫和緩衝動畫函數


最後,一點關於setInterval底層機制的擴展。測試

咱們內層函數的執行事件正常狀況下爲1-2s(測試過),而外層的循環須要3s才進行一次,正常的狀況是沒有問題的。可是,當你切換界面的時候,瀏覽器就會對setInterval函數產生影響,此時執行事件的事件就會超過3面,在沒移動結束的狀況下開啓另外一個定時器進行下一次圖片滾動,因此就會發生錯亂。

javascript是單線程的,當你使用setInterval函數的時候並非真正暫停,而是先掛起這個事件,繼續執行下面的事件,而當這個事件要執行時,若是瀏覽器當前沒有任務,那麼它會立馬執行,可是若是瀏覽器有任務,那麼就會有必定的延遲,這也是爲何切換界面會對setInterval函數的時間產生影響。

(關於setInterval函數的理解若有錯誤,歡迎指正!若是你們想要深刻理解,也能夠去一些大神的博客看一下setInterval函數的文章)

相關文章
相關標籤/搜索