LoginSignup
2
1

More than 3 years have passed since last update.

javascriptでタイマーを作る

Posted at

作ったもの

タイマー

使った技術

html, css, javascript

リンク

機能概要

  • カウントダウンできる
  • 測りたい時間を設定できる
  • 時間が経過したらアラームが鳴る
  • 途中でカウントダウンをストップできる
  • ストップした後、キャンセルボタンを押すとセットした時間に戻る

仕様

項目定義

タイマー

  • 時間(hours)
    • min: 0
    • MAX: 23
  • 分(minutes)
    • min: 0
    • MAX: 59
  • 秒(seconds)
    • min: 0
    • MAX: 59

ボタン定義

  • Start
    • hours ≠ 0 かつ minutes ≠ 0 かつ seconds ≠ 0のとき、Start ボタンを押下すると、カウントダウンが始まる
    • hours = 0 かつ minutes = 0 かつ seconds = 0のとき、Start ボタンを押下しても、画面上何も変化は起きない
    • ボタンを押下してカウントダウンが始まると、Stopボタンに変わる
  • Stop
    • カウントダウンが実行中のとき、ボタンを押下するとカウントダウンが中断する
    • Stopボタンが押下されると、自動的にRestartボタンに変わる
  • Restart
    • カウントダウンが中断中のとき、ボタンを押下するとカウントダウンが再開する
    • Restartボタンが押下されると、自動的にStopボタンに変わる
  • Reset
    • カウントダウン開始前、または実行中は、ボタンを押下できず、背景がグレーになっている
    • Stopボタンを押してカウントダウンが止まっているとき、ボタンの背景が青になり、押下できるようになる
    • Resetボタンを押すと、以下の通りの動作となる
      • タイマーがセレクトボックスに戻り、値は0時間0分0秒に戻る
      • RestartボタンがStartボタンに戻る
      • Resetボタンは背景がグレーになり、押下できなくなる

詳細設計

変数

  • second ... セレクトボックスに入力された秒の値を取得
  • minute ... セレクトボックスに入力された分の値を取得
  • hour ... セレクトボックスに入力された時間の値を取得
  • s ... secondを数値に変換して格納
  • m ... minuteを数値に変換して格納
  • h ... hourを数値に変換して格納
  • time ... カウントダウン用変数 (s, m, hを合計して秒数に変換)

関数

  • startCount()

    • 時間をセレクトボックスから設定し、スタートボタンを押したときに動作する
    • セレクトボックスの~時間 ~分 ~秒の数値をそれぞれdocument.getElementByIdで取得し、変数h, m, sに格納
    • 変数h, m, sを通して設定された時間を秒数に計算し直し、変数timeに格納
    • countStart()を呼び出し
  • countStart()

    • timeが0以上の時:
      • changeButtonToStopを呼び出す (StartボタンをStopボタンに変更する)
      • 時間表示を上書く
      • countEverySecを定義し、setInterval()を格納
      • 1000ミリ秒ごとに、関数countDown()を実行する
  • countDown()

    • time>0のとき
      • timeが1減少する
      • 変数h, m, sの値を上書き
        • h (時間) = time/3600(切り捨て)
        • m (分) = time/60(切り捨て) - h×60
        • s (秒) = time-h*3600-m*60
    • それ以外のとき
      • 繰り返し動作(countEverySec)を終了する
      • alertで”Time up!”という文字列を表示させる
      • タイムアップ時の音声を鳴らす
      • タイマー表示をセレクトボックスに戻す
      • StopボタンをStartボタンに戻す
  • stopCount()

    • Stopボタンが押されたときに実行される
    • 繰り返し動作(countEverySec)を終了する
    • 2つ配置されているボタンを"Restart"ボタン、"Reset"ボタンに変える (=StopボタンをRestartボタンに変える)
  • changeButtonToStart()

    • 2つ配置されているボタンを"Start"ボタン、"Reset"ボタンに変える
  • changeButtonToStop()

    • 2つ配置されているボタンを"Stop"ボタン、"Reset"ボタンに変える
  • restartCount()

    • カウントダウンがStopされ、Restartボタンが押されたときに実行
    • countStart()を呼び出す
  • reviseCountInput()

    • タイマーをカウントダウン表示からセレクトボックス表示に変更する
    • changeButtonToStart()を呼び出す

ソース

html
timer.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Timer</title>
    <link rel="stylesheet" type="text/css" href="style/timer.css">
    <link rel="shortcut icon" href="img/favicon.ico">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script type="text/javascript" src="js/timer.js"></script>

</head>

<body>
    <div class="top_area"></div>
    <div class="name">Timer</div>
    <div class="middle_area1"></div>

    <div id="timer">
      <select id="hours" class="timer_contents">
        <option>0</option>
        <option>1</option>
        <option>2</option>
        <option>3</option>
        <option>4</option>
        <option>5</option>
        <option>6</option>
        <option>7</option>
        <option>8</option>
        <option>9</option>
        <option>10</option>
        <option>11</option>
        <option>12</option>
        <option>13</option>
        <option>14</option>
        <option>15</option>
        <option>16</option>
        <option>17</option>
        <option>18</option>
        <option>19</option>
        <option>20</option>
        <option>21</option>
        <option>22</option>
        <option>23</option>
      </select>
      <p class="timer_contents"> 時間</p>
      <select id="minutes" class="timer_contents">
        <option>0</option>
        <option>1</option>
        <option>2</option>
        <option>3</option>
        <option>4</option>
        <option>5</option>
        <option>6</option>
        <option>7</option>
        <option>8</option>
        <option>9</option>
        <option>10</option>
        <option>11</option>
        <option>12</option>
        <option>13</option>
        <option>14</option>
        <option>15</option>
        <option>16</option>
        <option>17</option>
        <option>18</option>
        <option>19</option>
        <option>20</option>
        <option>21</option>
        <option>22</option>
        <option>23</option>
        <option>24</option>
        <option>25</option>
        <option>26</option>
        <option>27</option>
        <option>28</option>
        <option>29</option>
        <option>30</option>
        <option>31</option>
        <option>32</option>
        <option>33</option>
        <option>34</option>
        <option>35</option>
        <option>36</option>
        <option>37</option>
        <option>38</option>
        <option>39</option>
        <option>40</option>
        <option>41</option>
        <option>42</option>
        <option>43</option>
        <option>44</option>
        <option>45</option>
        <option>46</option>
        <option>47</option>
        <option>48</option>
        <option>49</option>
        <option>50</option>
        <option>51</option>
        <option>52</option>
        <option>53</option>
        <option>54</option>
        <option>55</option>
        <option>56</option>
        <option>57</option>
        <option>58</option>
        <option>59</option>
      </select>
      <p class="timer_contents"></p>
      <select id="seconds" class="timer_contents">
        <option>0</option>
        <option>1</option>
        <option>2</option>
        <option>3</option>
        <option>4</option>
        <option>5</option>
        <option>6</option>
        <option>7</option>
        <option>8</option>
        <option>9</option>
        <option>10</option>
        <option>11</option>
        <option>12</option>
        <option>13</option>
        <option>14</option>
        <option>15</option>
        <option>16</option>
        <option>17</option>
        <option>18</option>
        <option>19</option>
        <option>20</option>
        <option>21</option>
        <option>22</option>
        <option>23</option>
        <option>24</option>
        <option>25</option>
        <option>26</option>
        <option>27</option>
        <option>28</option>
        <option>29</option>
        <option>30</option>
        <option>31</option>
        <option>32</option>
        <option>33</option>
        <option>34</option>
        <option>35</option>
        <option>36</option>
        <option>37</option>
        <option>38</option>
        <option>39</option>
        <option>40</option>
        <option>41</option>
        <option>42</option>
        <option>43</option>
        <option>44</option>
        <option>45</option>
        <option>46</option>
        <option>47</option>
        <option>48</option>
        <option>49</option>
        <option>50</option>
        <option>51</option>
        <option>52</option>
        <option>53</option>
        <option>54</option>
        <option>55</option>
        <option>56</option>
        <option>57</option>
        <option>58</option>
        <option>59</option>
      </select>
      <p class="timer_contents"></p>
    </div>
    <div class="middle_area2"></div>
    <div class="buttons" id="buttons">
      <input type="button" class="button" id="startButton" value="Start" onclick=startCount()>
      <input type="button" class="button" id="resetButton" value="Reset" onclick=resetCount() disabled="true">
    </div>
    <audio id="timeUp" preload="auto">
      <source src="sound/alarm.mp3" type="audio/mp3">
    </audio>

    <!-- To avoid mobile audio issue -->
    <iframe src="sound/500-milliseconds-of-silence.mp3" allow="autoplay" id="silenceAudio" style="display:none"></iframe>

</body>
</html>

css
timer.css
body{
    margin: 0px;
    font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
    color: #636363;
}

.top_area {
    height: 50px;
    background-color: #FFFFFF;
}

.name{
    font-size: 28px;
    text-align: center;
}

.middle_area1{
    height: 50px;
    background-color: #FFFFFF;
}

#timer {
    font-size: 32px;
    text-align: center;
}

.timer_contents{
    display: inline-block;
    font-size: 24px;
}

.middle_area2{
    height: 20px;
    background-color: #FFFFFF;
}

.buttons{
    text-align: center;
}

.button:enabled{
    display: inline-block;
    width: 80px;
    height: 30px;
    background: #668ad8;
    margin: 0px 8px;
    font-size: 16px;
    color: #FFFFFF;
    border-radius: 6px;
    border-bottom: solid 4px #627295;
}

.button:disabled{
    display: inline-block;
    width: 80px;
    height: 30px;
    background: #a0a0a0;
    margin: 0px 8px;
    font-size: 16px;
    color: #FFFFFF;
    border-radius: 6px;
    border-bottom: solid 4px #627295;
}

js
timer.js

function startCount(){
    const second = document.getElementById("seconds").value;
    const minute = document.getElementById("minutes").value;
    const hour = document.getElementById("hours").value;
    s = Number(second);
    m = Number(minute);
    h = Number(hour);

    time = h*3600+m*60+s;
    console.log(h*3600+m*60+s);

    countStart();
}   

function countStart(){
    if (time>0) {
        changeButtonToStop();
        document.getElementById('timer').innerHTML = '<div id="timer">' + h + "時間 " + m +"" + s +"" + '</div>';  
        countEverySec = setInterval(countDown, 1000);
    }       
}



function countDown(){
    if (time>0) {
        time --;
        h = Math.floor(time/3600);
        m = Math.floor(time/60)-h*60;
        s = time-h*3600-m*60;
        document.getElementById('timer').innerHTML = '<div id="timer">' + h + "時間 " + m +"" + s +"" + '</div>';
    } else {
        clearInterval(countEverySec);
        document.getElementById("timeUp").play();
        alert("Time up!");
        reviseCountInput();
        changeButtonToStart();
    }
}

function stopCount(){
    clearInterval(countEverySec);
    document.getElementById("buttons").innerHTML = '<div class="buttons"><input type="button" class="button" id="restartButton" value="Restart" onclick=restartCount()><input type="button" class="button" id="resetButton" value="Reset" onclick=resetCount()></div>';
}

function changeButtonToStop(){
    document.getElementById("buttons").innerHTML = '<div class="buttons"><input type="button" class="button" id="stopButton" value="Stop" onclick=stopCount()><input type="button" class="button" id="resetButton" value="Reset" onclick=resetCount() disabled="true"></div>';
}

function changeButtonToStart(){
    document.getElementById("buttons").innerHTML = '<div class="buttons"><input type="button" class="button" id="startButton" value="Start" onclick=startCount()><input type="button" class="button" id="resetButton" value="Reset" onclick=resetCount() disabled="true"></div>';
}

function restartCount(){
    countStart();
}


function resetCount(){
    clearInterval(countEverySec);
    reviseCountInput();
}

function reviseCountInput(){
    document.getElementById("timer").innerHTML = '<div id="timer"><select id="hours" class="timer_contents"><option>0</option><option>1</option><option>2</option><option>3</option><option>4</option><option>5</option><option>6</option><option>7</option><option>8</option><option>9</option><option>10</option><option>11</option><option>12</option><option>13</option><option>14</option><option>15</option><option>16</option><option>17</option><option>18</option><option>19</option><option>20</option><option>21</option><option>22</option><option>23</option></select>'+' '+'<p class="timer_contents">時間</p>'+' '+'<select id="minutes" class="timer_contents"><option>0</option><option>1</option><option>2</option><option>3</option><option>4</option><option>5</option><option>6</option><option>7</option><option>8</option><option>9</option><option>10</option><option>11</option><option>12</option><option>13</option><option>14</option><option>15</option><option>16</option><option>17</option><option>18</option><option>19</option><option>20</option><option>21</option><option>22</option><option>23</option><option>24</option><option>25</option><option>26</option><option>27</option><option>28</option><option>29</option><option>30</option><option>31</option><option>32</option><option>33</option><option>34</option><option>35</option><option>36</option><option>37</option><option>38</option><option>39</option><option>40</option><option>41</option><option>42</option><option>43</option><option>44</option><option>45</option><option>46</option><option>47</option><option>48</option><option>49</option><option>50</option><option>51</option><option>52</option><option>53</option><option>54</option><option>55</option><option>56</option><option>57</option><option>58</option><option>59</option></select>'+' '+'<p class="timer_contents">分</p>'+' '+'<select id="seconds" class="timer_contents"><option>0</option><option>1</option><option>2</option><option>3</option><option>4</option><option>5</option><option>6</option><option>7</option><option>8</option><option>9</option><option>10</option><option>11</option><option>12</option><option>13</option><option>14</option><option>15</option><option>16</option><option>17</option><option>18</option><option>19</option><option>20</option><option>21</option><option>22</option><option>23</option><option>24</option><option>25</option><option>26</option><option>27</option><option>28</option><option>29</option><option>30</option><option>31</option><option>32</option><option>33</option><option>34</option><option>35</option><option>36</option><option>37</option><option>38</option><option>39</option><option>40</option><option>41</option><option>42</option><option>43</option><option>44</option><option>45</option><option>46</option><option>47</option><option>48</option><option>49</option><option>50</option><option>51</option><option>52</option><option>53</option><option>54</option><option>55</option><option>56</option><option>57</option><option>58</option><option>59</option></select>'+' '+'<p class="timer_contents">秒</p></div>'
    changeButtonToStart();
}

参考にしたリンク

解決できていないこと

タイムアップ時の音に関して、PCので実行した際には出るが、iPhoneのSafari, Chromeだと出ない。
以下サイトを参考に実装しているが、上記問題は未解決。
https://webty.jp/staffblog/production/post-907/
そもそもクリック等をトリガーとしないと、iPhoneではブラウザから音が出ない仕組みの様子。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1