原理解說
和時間相關的應用在javascript中主要有兩個函式 setTimeout
及 setInterval
:
- setTimeout - 在指定時間後執行某些指令或函式,只會執行一次。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<!--在網頁上先建立一個區塊並命名一個id或是class-->
<div class="counter"></div>
<script>
//先建立一個初始值
let start=0;
//宣告一個時間函式,並給予一個變數,
//如果沒有指定變數,那麼這個時間函式將會無法停止
let timeout=setTimeout(()=>{
//將初始值加1
start++;
//將結果寫入網頁中指令的dom中
//設定時間為三秒,所以要三秒後才會看到結果
document.querySelector('.counter').innerHTML=start;
},3000)
</script> - setInterval - 在指定的間隔時間持續執行某些指令或函式,沒有停止時間。由於以上的時間函式一旦執行後就會佔著一些記憶體空間,因此會搭配以下兩個函式來進行清楚或停止:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<!--在網頁上先建立一個區塊並命名一個id或是class-->
<div class="counter"></div>
<script>
//先建立一個初始值
let start=0;
//宣告一個時間函式,並給予一個變數,
//如果沒有指定變數,那麼這個時間函式將會無法停止
let interval=setInterval(()=>{
//將初始值加1
start++;
//將結果寫入網頁中指令的dom中
//設定時間為間隔一秒執行一次,
//所以每秒鐘都會執行一次加1的計算並把結果放到指令的dom中
document.querySelector('.counter').innerHTML=start;
},1000)
</script> - clearTimeout - 停止進行中的時間函式
1
2//函式中代入時間函式變數即可
clearTimeout(timeout) - clearInterval - 停止進行中的間隔時間函式
1
2//函式中代入時間函式變數即可
clearInterval(interval)
應用
一、快進時計
要讓數字有快進或慢進的感覺,基本上就是讓間隔時間變小,就會在畫面上呈現數字的快速變化效果,因此我們可以設定一個時間變化區間,然後把變化的量拿去除時間區間,就可以得到間隔時間,以下示範兩種時間函式的寫法,都可以得到一樣的結果:
1 | <!--在網頁上先建立一個區塊並命名一個id或是class--> |
1 | <!--在網頁上先建立一個區塊並命名一個id或是class--> |
二、進度條動畫
利用時間控制變量的原理,只要把時間和變量代入就可以做出任何動畫效果來,進度條的動畫效果一樣是有開始有結束,所以原理是一樣的,只是套用的對像從數字變成長度單位。
1 | <style> |
1 | let start=0; |
三、動態時間函式
上面兩種應用都是算出固定的時間間隔,然後變量也是固定的,如果我們希望變化的效果可以更豐富,比如先快後慢或是先慢後快,那就需要在時間變化上下功夫,原則上有兩個方向可以進行:
時間變化 - 固定每次的變量,但是時間不同,比如每次都加1,但是一開始是每秒加1,中間是0.5秒加1,最後是0.1秒加1。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62<!--在網頁上先建立一個區塊並命名一個id或是class-->
<div class="counter"></div>
<script>
let start=0; //起始值
let end=100; //結束值
let duration=9; //時間區間
let pt=0; //紀錄經過的時間
let times=new Array() //宣告一個陣列用來存放時間間隔
//使用迴圈來計算每個間隔時間的變化
for(let i=start;i<100;i++){
//在不同的時間區段計算不同的時間隔
if(pt<(duration*1000/3)){
//前面20個數字要在3秒內跑完,
//所以計算每個數字的時間間隔,並存入陣列
pt+= ((duration*1000/3)/20)
times.push(((duration*1000/3)/20))
}else if(pt<(duration*1000/3*2)){
//中間50個數字要在3秒內跑完,
//所以計算每個數字的時間間隔,並存入陣列
pt+= ((duration*1000/3)/60)
times.push(((duration*1000/3)/60))
}else{
//最後20個數字要在3秒內跑完,
//所以計算每個數字的時間間隔,並存入陣列
pt+= ((duration*1000/3)/20)
times.push(((duration*1000/3)/20))
}
}
let run=setTimeout(()=>{
tf()
},times[0])
let ti=0; //這是一個時間索引,對應到的是times陣列
function tf(){
if(start>=end){
clearTimeout(run)
return;
}
document.querySelector(".counter").innerHTML=start;
ti++;
//每次執行完時間函式後,
//再開一個新的時間函式並且指定新的時間
run=setTimeout(()=>{
tf()
},times[ti])
}
</script>變量變化 - 固定間隔時間,但每次的變量不同,比如每次的時間間隔都是0.5秒,但是一開始時每次加1,中間每次加2,最後每次加3;這種模式比較適合用在圖形動畫上。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<style>
.progress-box{
width:200px;
height:20px;
background:lightgreen;
border:1px solid darkgreen;
}
.progress-line{
width:0px;
height:20px;
background:green;
}
</style>
<div class='progress-box'>
<div class='progress-line'>
</div>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21let start=0;
let end=150;
let line=setInterval(()=>{
if(start>=end){
clearInterval(line)
return;
}
//根據不同的變量區間來決定每次變量的不同
if(start<20){
start++;
}else if(start<60){
start+=2;
}else{
start+=4;
}
document.querySelector(".progress-line").style.width=start+"px";
},100)
當然,要做出更複雜的效果,也可以考慮讓時間和變量都是動態不固定的。