ChatGPTに教えてもらいながらタイマーを作る
2024年5月25日
みなさんこんにちは。
ケミストのWeb担当みやのです。
「Web」記事では、これまでに得たWebに関する知識を記録として残していきたいと思います。
今回はこの前のストップウォッチに続いて「カウントダウンタイマー」を作ってみました。
カウントダウンするタイマーといえば・・・やっぱコレですよね。
アンビリカルケーブル断線!
エ〇゛ァ、内部電源に切り替わりました!
ChatGPTに聞いてみた
またまたChatGPTに質問させていただきましたァン!
「JavaScriptでカウントダウンタイマーを作りたいです」
「5分のタイマーを作りたいです」
「100分の1秒で作りたいです」
「リセットボタンを実装できますか」
「スタートボタンとストップボタンを1つにまとめられますか」
「スタート、ストップ、リセットを漢字にするとどうなりますか」
「自分で時間を設定できるようにしたいです」
「プラスボタンやマイナスボタンで時間を変更するようにできますか」
「タイマー部分を直接変更するようにできますか」
「マイナスの数値を入力できないようにしたいです」
「input部分を非表示にできますか」
「ミリ秒部分だけ文字を小さくできますか」
「残り1分を切ったら文字の色を赤くできますか」
「画像の上にタイマーを重ねることはできますか」
「残り1分を切ったら画像を切り替えることはできますか」
「ブラウザのタイトル部分に残り時間を表示できますか」
などと質問攻めにしてみました。
質問するたびに「もちろんです!」と返答してくれて、何か......その
さわやかなヤツでした.........
AIなのに奇妙なんですけれど...
コードは以下の通りです。ものすごく長くなってしまいました。
<div class="parent">
<img id="image" src="img/eva1.svg" alt="Image">
<div id="timer" class="child">05:00<span id="millis">:00</span></div>
</div>
<button onclick="adjustTimeDirect('minutes', -1)">-</button>
<input type="number" id="minutes" min="0" value="5" class="d-none">
<span>分</span>
<button onclick="adjustTimeDirect('minutes', 1)">+</button>
<button onclick="adjustTimeDirect('seconds', -1)">-</button>
<input type="number" id="seconds" min="0" max="59" value="0" class="d-none">
<span>秒</span>
<button onclick="adjustTimeDirect('seconds', 1)">+</button>
<button id="startStopBtn" onclick="startStopCountdown()">開始</button>
<button class="btn btn-danger" onclick="resetCountdown()">再設定</button>
.parent {
position: relative;
}
.child {
position: absolute;
top: 10%;
left: 10vw;
font-size: 20vw;
}
let countdownInterval;
let countdownEndTime;
let isCountdownRunning = false;
let initialTime;
function startStopCountdown() {
if (isCountdownRunning) {
stopCountdown();
} else {
startCountdown();
}
}
function startCountdown() {
const minutes = parseInt(document.getElementById("minutes").value, 10) || 0;
const seconds = parseInt(document.getElementById("seconds").value, 10) || 0;
const currentTime = new Date().getTime();
const duration = minutes * 60 * 1000 + seconds * 1000;
if (isCountdownRunning) {
clearInterval(countdownInterval);
}
countdownEndTime = currentTime + duration;
initialTime = duration;
countdownInterval = setInterval(updateCountdown, 10);
isCountdownRunning = true;
document.getElementById("startStopBtn").innerText = "停止";
}
function stopCountdown() {
clearInterval(countdownInterval);
isCountdownRunning = false;
document.getElementById("startStopBtn").innerText = "開始";
}
function resetCountdown() {
if (isCountdownRunning) {
return;
}
stopCountdown();
updateDisplay(initialTime);
document.getElementById("image").src = "img/eva1.svg";
resetInputFields();
resetTextColor();
}
function onMillisZero() {
document.getElementById("image").src = "img/eva2.svg";
}
function updateCountdown() {
const currentTime = new Date().getTime();
const remainingMillis = countdownEndTime - currentTime;
if (remainingMillis <= 50) {
document.getElementById("timer").innerHTML = "00" + ":" + "00" + "<span id='millis'>:" + "00" + "</span>";
if (remainingMillis <= 0) {
stopCountdown();
alert("カウントダウン終了!");
}
} else {
updateDisplay(remainingMillis);
if (remainingMillis < 60000) {
onMillisZero();
document.getElementById("timer").style.color = "red";
} else {
document.getElementById("timer").style.color = "orange";
}
}
}
function updateDisplay(remainingMillis) {
const minutes = Math.floor(remainingMillis / (60 * 1000));
const seconds = Math.floor((remainingMillis % (60 * 1000)) / 1000);
const millis = remainingMillis % 1000;
const formattedTime = formatTime(minutes) + ":" + formatTime(seconds);
const formattedMillis = formatMillis(millis);
document.getElementById("timer").innerHTML = formattedTime + "<span id='millis'>:" + formattedMillis + "</span>";
document.title = formattedTime;
}
function adjustTimeDirect(inputId, value) {
const inputElement = document.getElementById(inputId);
let currentValue = parseInt(inputElement.value, 10) || 0;
currentValue += value;
if (inputId === 'minutes') {
currentValue = Math.min(Math.max(currentValue, 0), 99);
}
if (inputId === 'seconds') {
currentValue = Math.min(Math.max(currentValue, 0), 59);
}
inputElement.value = currentValue;
updateDisplay((parseInt(document.getElementById("minutes").value, 10) || 0) * 60 * 1000 + (parseInt(document.getElementById("seconds").value, 10) || 0) * 1000);
}
function formatTime(time) {
return time < 10 ? "0" + time : time;
}
function formatMillis(millis) {
return millis.toString().slice(-2).padStart(2, '0');
}
function resetTextColor() {
document.getElementById("timer").style.color = "orange";
}
問題点
リセットボタンの挙動がややおかしいです。
画面読み込み直後にリセットボタンを押すと表示がおかしくなります(NaNというのはNot a Numberのことらしいです)
スタート→ストップ→再スタートした時にカウントが最初からになってしまうという問題がどうしても解決できなかったです。
タイマーがゼロになった時、ミリ秒の部分がちょうど00になってくれないので、50ミリ秒(適当)でタイマーを00:00:00にするようにしました。
ボタン長押しで数値がピピピ~っと増減するようにしたかったのですが無理でした。
まとめ
今回もChatGPTに大いに助けてもらいましたが、自分でスクリプトを書く練習もしないとですね。
そのうちBGMとか効果音とかを組み込んでみたいです。