js中clearInterval無效,以及setInterval中斷後重新執行

引言:

網頁中的效果:網頁上向右運動的span,背景圖片隨着向右移動而不斷切換。在鼠標移入圖片時,停止向右運動,並改變爲特定的背景圖片;當鼠標移出時,繼續向右移動並不斷切換背景圖片,直到運動到右端停止運動及圖片切換。向右運動以及圖片切換效果均是由setInterval週期性調用函數實現,停止運動則需要clearInterval函數實現。
在實現過程中容易出現以下問題:
    鼠標移入時不能停止運動,或者是移動速度加快,clearInterval無效鼠標移出後,運動到最右端不能停止,clearInterval無效;

導致出現這個問題的原因爲:
setInterval()每執行一次,則返回一個唯一id。所以setInterval()執行了n次,那麼需要調用clearInterval()也是n次。出現clearInterval()失效的情況,請查看每次調用setInterval()是否都clearInterval()了。


本篇文章中,通過對該效果的實現,解決這兩個問題。

說明:對於本篇文章中涉及到的知識點,只做簡單說明,詳細信息請查找相關資料。

一、佈局

在head中引用css文件,body中,主要爲一個div,爲主要顯示效果區域,id="show",position屬性設置爲relative,讓其他元素以此爲基準進行定位;show中爲三個span,id分別爲run,wait,end;在run中,實現圖片的右移和圖片切換,以及鼠標移入時停止移動並切換鼠標移入時的背景圖片,移動到右端wait處停止移動;wait在右端切換圖片,直到run移動到該處時,與run一起不可見,同時,end可見。
html代碼片段:

<div id="show">
	<span class="showbody" id="run" onMouseOver="mouseOver()" onMouseOut="mouseOut()"></span>
	<span class="showbody" id="end"></span>
	<span class="showbody" id="wait"></span>
</div>

css代碼片段:

#show{
	position:relative;
	top:100px;
	height:100px;
	margin:auto;
	border-bottom:4px solid green;
}	

.showbody{
	height:40px;
	position:absolute;
	display:block;
	bottom:0px;
	background-repeat:no-repeat;
}
.run{
	background-image:url(../img/run.png) ;
	background-position:0px 0px;
	width:226px;
	height:40px;
}
.wait{
	background-image:url(../img/wait.png) ;
	background-position:0px 0px;
	width:90px;
	height:56px;
	right:0px;
}
.end{
	background-image:url(../img/end.png) ;
	width:90px;
	height:56px;
	right:0px;
	visibility:hidden;
}
主要涉及知識:

1、相對定位與絕對定位:

    position:absolute:絕對定位,它是脫離文檔流的。

    position:relative:相對定位,不會脫離文檔流。

2、設置單邊效果:
    border-bottom:4px solid green;//設置底部邊框爲實線,其他邊框不可見。
3、行內元素與塊級元素:
    display:block;//由於span爲行內元素,設置其寬、高等屬性無效。

二、圖片切換效果

通過設置圖片在Y軸方向上的位置,來實現圖片的切換,以wait爲示例代碼,run的切換爲

//wait背景圖片切換
var waitD= document.getElementById("wait");
var waitFlag = 0;
function waiting(){
	if(waitFlag%4==0){
		waitD.style.backgroundPositionY='0px';
	}else if(waitFlag%4==1){
		waitD.style.backgroundPositionY='-56px';
	}else if(waitFlag%4==2){
		waitD.style.backgroundPositionY='-112px';
	}else if(waitFlag%4==3){
		waitD.style.backgroundPositionY='-168px';
	}
	waitFlag++;
}
主要涉及知識:

1、文檔流中座標圖以左上角爲原點,向下爲Y軸的正方向,向右爲X軸的正方向,顯示器正面爲Z軸正方向,如下所示:

類似於高中數學XYZ軸三維空間模型:數學中,向上爲Y軸正方向;在文檔流中,向下爲Y軸正方向。
屬性 描述
background 在一行中設置所有的背景屬性
backgroundAttachment 設置背景圖像是否固定或隨頁面滾動
backgroundColor 設置元素的背景顏色
backgroundImage 設置元素的背景圖像
backgroundPosition 設置背景圖像的起始位置
backgroundPositionX 設置backgroundPosition屬性的X座標
backgroundPositionY 設置backgroundPosition屬性的Y座標
backgroundRepeat 設置是否及如何重複背景圖像
本示例中主要用backgroundPositionY,來改變圖片的顯示:
document.getElementById("wait")
.style.backgroundPositionY='0px';

三、向右移動

function runing()實現了一次向右移動一定偏移量,切換一次圖片,移動後判斷是否需要停止移動。通過setInterval()週期性的調用running(),實現不斷右移效果。

/<span style="font-size:14px;">/向右移動
var runDiv = document.getElementById("run");
function runing(){
		var r = 80;//向右移動的偏移量--即每次右移80px
		//1 向右運動
		runDiv.style.left = runDiv.offsetLeft+r+"px";//run的左邊距設置爲run的寬度+80px,即每次右移80px

		//2 圖片切換
		var left = parseInt(runDiv.style.left);//將返回的像素字符串轉換爲數字,如60px -> 60
		runChange(left,r);//run圖片切換
		
		//4 是否停止運動,停止時end可見
		runStop(left);	
	}</span>
主要涉及知識:

1、setInterval() 方法:

setInterval() 方法可按照指定的週期(以毫秒計)來調用函數或計算表達式。

setInterval() 方法會不停地調用函數,直到 clearInterval() 被調用或窗口被關閉。

由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的參數。

語法:setInterval(code,millisec[,"lang"])

參數 描述
code 必需。要調用的函數或要執行的代碼串。
millisec 必須。週期性執行或調用 code 之間的時間間隔,以毫秒計。
返回值:一個可以傳遞給 Window.clearInterval() 從而取消對 code 的週期性執行的值。
本示例中,通過調用方法setInterval()週期性的調用圖片切換函數,來實現向右移動過程中不斷切換圖片的效果和右端不斷切換的效果。

四、添加mouse事件

鼠標移入,run停止右移,背景圖片換位特定的圖片;鼠標移出,run繼續右移,背景圖片繼續切換;

其中使用clearInterval() 方法時需要注意的是:clearInterval() 方法的參數必須是由 setInterval() 返回的 ID 值。這一點很重要!!

進入頁面,setInterval()調用runing()方法,使run向右移動;在鼠標移入時,調用clearInterval()清除setInterval() 設置的 timeout,移出時setInterval()繼續調用runing()方法向右移動。鼠標移出時setInterval()返回的id與剛進入頁面時setInterval()返回的id,是兩個id,即setInterval()每執行一次,則返回一個唯一id。所以setInterval()執行了n次,那麼需要調用clearInterval()也是nci。出現clearInterval()失效的情況,請查看每次調用setInterval()是否都clearInterval()了。


本示例中,mouseOver()中調用setInterval
();mouseOut()中調用clearInterval()。用mouseOutFlag來標記是否有鼠標移出事件。在鼠標移入時,判斷在本次鼠標移入之前,是否有鼠標移出,如果有,則調用clearInterval(),取消由 setInterval() 設置的 timeout。目的是確保只有setIntervalsetInterval一個setInterval()調用runing()方法。

//鼠標移入時,更換背景圖片圖片,停止運動
var intR1=0;//mouseOut()處調用setInterval的返回Id
var mouseOutFlag=0;//是否調用mouseOut()標誌
function mouseOver(){
//如果不是第一次,則停止上一次的setInterval
	if(mouseOutFlag!=0){
		window.clearInterval(intR1);
	}
	runDiv.style.backgroundImage="url(./img/hover.png)";//設置背景圖片
	runDiv.style.backgroundPositionY='0px';//設置圖片在Y軸上的位置
	runDiv.style.backgroundPosition='center center';//設置圖片位置爲上下居中,左右居中
	window.clearInterval(intR);
}
//鼠標移出時,繼續向右移動,圖片繼續切換
function mouseOut(){
	mouseOutFlag=1;
	//run從停止的地方繼續運動,且圖片從停止的地方繼續切換
	runDiv.style.backgroundImage="url(./img/run.png)";//設置設置背景圖片
	runDiv.style.backgroundPositionY='0px';//設置圖片在Y軸上的位置
	//從停止的地方繼續向右移動
	intR1=self.setInterval("runing()",400);
}


主要涉及知識:

1、onMouseOver事件屬性:當鼠標指針移動到圖像上時執行一段 JavaScript;
2、onMouseOut事件屬性:當鼠標指針移出圖像時執行一段 JavaScript;

3、clearInterval()方法:

clearInterval() 方法可取消由 setInterval() 設置的 timeout。

clearInterval() 方法的參數必須是由 setInterval() 返回的 ID 值。

語法:clearInterval(id_of_setinterval)

參數 描述
id_of_setinterval 由 setInterval() 返回的 ID 值。


五、移動到右端停止

1、判斷移動到右端:run的左外邊距小於等於show的寬度減去wait的寬度;

2、使用window.clearInterval(intR),停止run的向右移動以及圖片切換,同時visibility屬性設置爲不可見;wait停止圖片切換,visibility屬性設置爲不可見;end的visibility屬性設置爲可見。

停止移動時,也需要判斷是否有鼠標移出事件中的setInterval(),如果有,則需要調用clearInterval()來停止右移

//停止<span style="font-family:Microsoft YaHei;">移</span>動
function runStop(left){
	var showWidth = parseInt(document.getElementById("show").offsetWidth);//獲取show的寬度
	var runWidth = parseInt(runDiv.offsetWidth);//獲取run的寬度
	if(left==(showWidth-runWidth) || left>(showWidth-runWidth)){//運動到靠近end時:run的左外邊距,小於等於。。。
		if(mouseOutFlag==1){//調用了mouseOut()函數,則停止
			window.clearInterval(intR1);
		}
		window.clearInterval(intR);//從mouseOut()處停止調用runing函數
		window.clearInterval(intW);//停止調用waiting函數
		runDiv.style.visibility="hidden";//run不可見
		waitD.style.visibility="hidden";//wait也不可見
		document.getElementById("end").style.visibility="visible";//end可見
	}
}
主要涉及知識:

1、parseInt("1px");//將返回的像素字符串轉換爲數字--->結果1
2、document.getElementById("run").style.left="1px";//設置run的左邊距
3、document.getElementById("show").offsetWidth;//獲取show的寬度
4、document.getElementById("run").style.visibility="hidden";//run不可見
5、clearInterval()方法。

完整的代碼如下所示:
<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>HUAWEI-V8</title>
  <link rel="stylesheet" href="css/V8.css" type="text/css" />
 </head>
 <body>
   <div id="show">
		<span class="run showbody" id="run" onMouseOver="mouseOver()" onMouseOut="mouseOut()"></span>
		<span class="end showbody" id="end"></span>
		<span class="wait showbody" id="wait"></span>
    </div>


<script>
	var runDiv = document.getElementById("run");
	var waitD= document.getElementById("wait");
	var waitFlag = 0;

	//按照指定的週期(以毫秒計)來調用函數或計算表達式。
	var intW=self.setInterval("waiting()",400);
	var intR=self.setInterval("runing()",400);//每400毫秒調用一次runing()函數,實現run位置的右移
	var intR1=0;//mouseOut()處調用setInterval的返回Id
	var mouseOutFlag=0;//是否調用mouseOut()標誌
			
	//向右移動
	function runing(){
		var r = 80;//向右移動的偏移量--即每次右移80px
		//1 向右運動
		runDiv.style.left = runDiv.offsetLeft+r+"px";//run的左邊距設置爲run的寬度+80px,即每次右移80px

		//2 圖片切換
		var left = parseInt(runDiv.style.left);//將返回的像素字符串轉換爲數字,如60px -> 60
		runChange(left,r);//run圖片切換
		
		//4 停止運動,end可見
		runStop(left);	
	}
	
	//run背景圖片切換
	function runChange(left,r){
		if((left/r)%3==0){
			runDiv.style.backgroundPositionY='0px';
		}else if((left/r)%3==1){
			runDiv.style.backgroundPositionY='-40px';
		}else if((left/r)%3==2){
			runDiv.style.backgroundPositionY='-80px';
		}
	}
	
	//停止運動
	function runStop(left){
		var showWidth = parseInt(document.getElementById("show").offsetWidth);//獲取show的寬度
		var runWidth = parseInt(runDiv.offsetWidth);//獲取run的寬度
		if(left==(showWidth-runWidth) || left>(showWidth-runWidth)){//運動到靠近end時:run的左外邊距,小於等於。。。
			if(mouseOutFlag==1){//調用了mouseOut()函數,則停止
				window.clearInterval(intR1);
			}
			window.clearInterval(intR);//從mouseOut()處停止調用runing函數
			window.clearInterval(intW);//停止調用waiting函數
			runDiv.style.visibility="hidden";//run不可見
			waitD.style.visibility="hidden";//wait也不可見
			document.getElementById("end").style.visibility="visible";//end可見
		}
	}
	//wait背景圖片切換
	function waiting(){
		if(waitFlag%4==0){
			waitD.style.backgroundPositionY='0px';
		}else if(waitFlag%4==1){
			waitD.style.backgroundPositionY='-56px';
		}else if(waitFlag%4==2){
			waitD.style.backgroundPositionY='-112px';
		}else if(waitFlag%4==3){
			waitD.style.backgroundPositionY='-168px';
		}
		waitFlag++;
	}
	//鼠標移入時,更換背景圖片圖片,停止運動
	function mouseOver(){
		//如果不是第一次,則停止上一次的setInterval
		if(mouseOutFlag!=0){
			window.clearInterval(intR1);
		}
		runDiv.style.backgroundImage="url(./img/hover.png)";//設置背景圖片
		runDiv.style.backgroundPositionY='0px';//設置圖片在Y軸上的位置
		runDiv.style.backgroundPosition='center center';//設置圖片位置爲上下居中,左右居中
		window.clearInterval(intR);
	}
	//鼠標移出時,繼續向右移動,圖片繼續切換
	function mouseOut(){
		mouseOutFlag=1;
		//run從停止的地方繼續運動,且圖片從停止的地方繼續切換
		runDiv.style.backgroundImage="url(./img/run.png)";//設置設置背景圖片
		runDiv.style.backgroundPositionY='0px';//設置圖片在Y軸上的位置
		//從停止的地方繼續向右移動
		intR1=self.setInterval("runing()",400);
	}
</script>

</body>
</html>



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章