JavaScript教學-從打造一個計時器裡認識JavaScript!(下)


今日是JavaScript計時器教學的下篇,今日我們會將上次教學的簡化版計時器內容,改成像上面這張圖片這樣,較為精緻、功能上也較多的完整計時器,如果你是還沒看過上一篇內容的朋友,連結在這裡喔!


JavaScript計時器 程式實作

接續上次我們所實作的簡化版,相信現在你對於JavaScript是如何和靜態的Html元素做互動有一個基本的概念了,基本上就是我們透過id找到特定元素之後,針對元素做值以及程式邏輯上的運用而已,非常的簡單,所以我們今天要繼續用這個概念實作出更完整的計時器,上次的計時器只達到能夠讓使用者倒數計時而已,並不能夠像是一般的計時器去輸入時、分、秒,也不能倒計數到一半就做停止或者重設,並且在顯示上也不夠直觀,所以我們今天就會將這些一項一項完成,那就開始吧!

顯示時、分、秒

<meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous"> 
<STYLE>
        <!--
        input{
            font-size:180px ;
            width: 20%;
            float:left;
            text-align:center;
        }
        p{
            font-size:180px; 
            float:left
        }
        -->
  </STYLE>
  </head>
  <body>
    <h1>JavaScript教學-計時器</h1>    
    <div style="margin:0px auto; width:80%;" >
    <input
        onkeyup="value=value.replace(/[^\d]/g,'') " 
        ng-pattern="/[^a-zA-Z]/"    
        value= 0
        maxlength="2"
        onblur="setHour()"
        onchange = "checkNumber(value,id)"
        id = "setHour";
    ></input>
    <p> &nbsp:&nbsp</p>
    <input
        onkeyup="value=value.replace(/[^\d]/g,'') " 
        ng-pattern="/[^a-zA-Z]/"    
        value= 0 
        maxlength="2"
        onblur="setMinute()"
        id = "setMinute";
    ></input>
    <p>&nbsp:&nbsp</p>
    <input
        onkeyup="value=value.replace(/[^\d]/g,'') " 
        ng-pattern="/[^a-zA-Z]/"    
        value= 0
        maxlength="2"
        onblur="setSecond()"
        id = "setSecond";
    ></input> 
    </div>
    <div >
        <button     
        style="width:15% ;height:100px;position: absolute; top:55%;left:20%;font-size: 50px;"
        class="btn btn-success"
        id = "start"
        onclick = "startCounting()"
        >開始</button>
        <button
        style="width:25% ;height:100px;position: absolute; top:55%;left:45%;font-size: 50px"
        class="btn btn-primary"
        onclick = "addMinute()"
        id= "reset"
        >增加一分鐘</button>
    </div>

看起來很長,但其實都是在重複相同的東西而已,首先是我們對於時、分、秒,為了要讓其能夠有讓使用者輸入的效果,我們必須要使用Input欄位,並且我們為了保證使用者不會對於Input搞怪,所以我們設置了onkeyup以及ng-pattern的正規式,來避免使用者隨便輸入數字以外的東西導致程式當機,並且我們限制分和秒最大長度為2位數,避免百位數的出現,不過我寫到後面發現這樣並沒有辦法規避六十以上的數字,會有更好的方法的,此處只是告訴大家這是一個方式,接著我們必須要使用onBlur()的方法,這代表只要你Input過後將滑鼠移開,就會觸發onBlur()裡面的方法,這樣子我們就可以確保使用者輸入的內容可以馬上被接收到,這邊大致為了接下來JavaScript的內容需要先準備的HTML和CSS的部分,而在前面的部分我有使用到一點BootStrap來讓畫面變得更加好看,完全不了解BootStrap的同學只要知道我等於是引入了一個超大CSS檔案,然後去找到對應的Class套用他們的style而已,詳情大家可以參考這篇文章。

https://tw.alphacamp.co/blog/bootstrap-4-introduction

接受使用者輸入的時間

let hour = 0;
let minute = 0;
let second = 0;
function setHour(){
    hour = parseInt(document.getElementById("setHour").value)
    console.log(hour)
}
function setSecond(){
    let setSecond = document.getElementById("setSecond")
    second = parseInt(setSecond.value)
    console.log(setSecond)
    if(second>=60){
        second = 59
        //調整該項目
        setSecond.value = 59
    }
    console.log(second)
}
function setMinute(){
    let setMinute = document.getElementById("setMinute") 
    minute = parseInt(setMinute.value)
    if(minute>=60){
        minute = 59
        //調整該項目
        setMinute.value = 59
    }
}

這邊我們只需要觀看setSecond()方法就可以明白其他兩者的運作方式了,都是大同小異的,首先一樣都是透過document.getElementById接受使用者的setMinute標籤,再來要注意的是,由於使用者輸入在input的欄位會被JavaScript默認為字串,所以我們必須要將其先用parseInt()的方法轉換為數字,而再來則是我們必須要判斷這個數字有沒有大於60,由於如果大於60就不是時間了,所以只要大於60我們一率將其設置為59,而小時和秒的設定我們只需要以此類推,這樣就完成了!

開始計時

let timer = 0;
function startCounting(){
    //確保value沒跑掉
    setHour =  document.getElementById("setHour")
    setSecond =  document.getElementById("setSecond")
    setMinute =  document.getElementById("setMinute")
    hour = parseInt(setHour.value)
    second = parseInt(setSecond.value)
    minute = parseInt(setMinute.value)
    if(hour === 0 && second === 0 && minute === 0){
        console.log("不會執行")
    }else{
        timer = window.setInterval("Check_Time()", 1000);
        //將input field屬性做更改 不能更改 且可以改變樣式
        setHour.setAttribute('disabled','disabled')
        setMinute.setAttribute('disabled','disabled')
        setSecond.setAttribute('disabled','disabled')
        //改變button樣式讓其能夠呼叫中斷時間的方法
        const start = document.getElementById("start")
        const reset = document.getElementById("reset")
        start.innerHTML ="暫停"
        start.setAttribute('onclick','stopCounting()')       
        start.setAttribute('class',"btn btn-danger")
        reset.setAttribute('onclick','reset()')
        reset.innerHTML = "重設"
        reset.setAttribute('class',"btn btn-dark")
    }         
}

此處程式碼看起來稍微冗長一點,原因是因為我們必須同時操縱三個Input欄位的狀態,但其實邏輯並不複雜,首先這個方法是和開始按鈕的Button做連結的,此處我們仍然需要再次接受三個欄位,原因是我們待會需要對其的狀態做操控,並且我們也需要再次接受使用者所輸入的欄位,而這邊其實不需要再次接受,因為透過剛剛onBlur()的方法,我們寫在全域變數裡面的變數一定會是使用者輸入最新的數字,不過再接收一次這樣也可以避免一些意想不到的狀況發生。

而接下來我們需要確認使用者是不是有Input時間,也就是如果時間皆為0的話,那也不需要計時了,所以我們就讓開始按鈕不會去執行任何東西。
而如果能夠執行的話,和上次的文章一樣,我們利用setInterval()以每一秒執行一次的方式執行倒數的方法,並且我們需要讓原本的Input欄位變得無法更改,否則開始倒計時卻還能改變數字會是一個大bug,而我們透過setAttribute()這個方法來實現,此方法是用來操縱HTML元素內的屬性,跟上篇文章只改變value不一樣,也是一個實用的方法。

並且我們還需要改變按鈕鎖定的方法和樣式,將開始改為暫停,還有其onclick會觸發的方法也做修改,到這邊就完成了開始計時!

倒數計時

const audio = new Audio("clock.mp3");
function Check_Time() {
    //check到了沒有
    if(hour === 0 && second === 0 && minute === 0){
        audio.play();
        alert("時間到了")  
        audio.pause()            
        stopCounting()
        return
    }
    second -=1
    if(second === -1 ){ //如果秒數是-1代表減過頭了
        second = 59 //換秒
        minute-=1 //扣除minute
    }
    if(minute === -1 ){ //如果秒數是-1代表減過頭了
        minute = 59 //換分
        hour-=1 //扣除小時
    }
    let htmlHour = document.getElementById("setHour")
    let htmlSecond = document.getElementById("setSecond")
    let htmlMinute = document.getElementById("setMinute")
    htmlHour.value = hour
    htmlMinute.value = minute
    htmlSecond.value = second
}

倒數計時時一樣首先要確認的是時間到了沒有,而這次我們加入了簡單的鬧鈴,通過audio這個函式,可以播放鬧鈴聲,記得必須要將想要設置的鬧鈴mp3放到和程式同樣的資料夾才能觸發,時間到之後,我們會觸發停止計時來去做停止之後的邏輯。

而接下來計時的部分也非常簡單,每次都會去做扣除秒數的部分,而如果秒數到達0以下了,我們就將其改為59並且將分減一,而在分的部分也以此類推就好,最後再將改完的時、分、秒重新分配給HTML元素就完成倒數計時的功能了。

暫停計時

function stopCounting(){
    clearInterval(timer)
    document.getElementById("setHour").removeAttribute('disabled')
    document.getElementById("setSecond").removeAttribute('disabled')
    document.getElementById("setMinute").removeAttribute('disabled')
    const start = document.getElementById("start")
    const reset = document.getElementById("reset")
    start.innerHTML ="開始"
    start.setAttribute('onclick','startCounting()')    
    start.setAttribute('class',"btn btn-success")    
    reset.setAttribute('onclick','addMinute()')
    reset.innerHTML = "增加一分鐘"
    reset.setAttribute('class',"btn btn-primary")   
}

此處非常簡單,首先我們將timer清除,再來我們將原本不可更改的input欄位變得可以更改,然後更改暫停按鈕的樣式就可以了,基本上和開始計時沒有兩樣。

重設和增加一分鐘

function addMinute(){
    minute +=1
    if(minute>59){
        minute = 0
        hour +=1 
    }
    let htmlHour = document.getElementById("setHour")
    let htmlMinute = document.getElementById("setMinute")
    htmlHour.value = hour
    htmlMinute.value = minute
}
function reset(){
    document.getElementById("setHour").value = 0
    document.getElementById("setSecond").value = 0
    document.getElementById("setMinute").value = 0
    stopCounting()
}

這是兩個簡單卻對於整個計時器的完整度不可或缺的功能,首先增加一分鐘就是增加全域變數中minute的個數再將其分配到HTML元素就好,但我們還必須注意小時數的增加,所以必須在其要加到60的時候去設置讓小時數加一,而我們也可以用同樣的道理去設置增加十分鐘、增加二十分鐘等等

再來則是重置,重置一樣是更改HTML裡的元素全部設為0,之後再去觸發停止計時的按鈕就可以完成重設了。

到此我們就完成整個計時器的功能了,是不是非常簡單呢!看似簡單其實卻運用了很多JavaScript的各個功能,以上就是JavaScript計時器的教學了。

你接下來想看什麼樣的實作作品呢!歡迎留言在下方給我,我都一定會回覆並且寫出更好品質的教學給各位喔!

馬上看–Python爬蟲教學 -試著作自己的搶購機器吧!(上)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *