アプリ版:「スタンプのみでお礼する」機能のリリースについて

HTMLとJavaScriptで作ったタイマーアプリが正常に動作しなくて困っています。以下がそのコードです。まだ整理していないので、タイマーの位置などが変ですが。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>タイマーアプリ</title>
<style>
form {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}

label {
font-size: 24px;
margin-bottom: 16px;
}

input {
font-size: 24px;
padding: 8px;
margin-bottom: 16px;
text-align: center;
}

button {
font-size: 24px;
padding: 8px 16px;
margin: 8px;
}

#display {
font-size: 48px;
margin-bottom: 16px;
}
</style>
</head>
<body>
<form>
<label for="time">タイマーの長さ(秒):</label>
<input type="number" id="time" name="time" min="1" required>
<button id="start" onclick="startTimer(event)">スタート</button>
<button id="pause" onclick="pauseTimer(event)">一時停止</button>
<button id="reset" onclick="resetTimer()">リセット</button>
</form>

<div id="display">0:00</div>

<script>
let timeLeft = 0;
let timerId = null;
let pausedTime = 0;

function startTimer(event) {
event.preventDefault();
if (timerId !== null) {
return;
}

timeLeft = parseInt(document.getElementById("time").value);
timerId = setInterval(() => {
timeLeft--;
if (timeLeft === 0) {
clearInterval(timerId);
timerId = null;
playSound();
}
updateDisplay();
}, 1000);
}

function pauseTimer(event) {
event.preventDefault();
if (timerId !== null) {
clearInterval(timerId);
timerId = null;
pausedTime = timeLeft;
document.getElementById("pause").textContent = "再開";
} else {
timeLeft = pausedTime;
startTimer(event);
document.getElementById("pause").textContent = "一時停止";
}
}

function resetTimer() {
if (confirm("本当にリセットしますか?")) {
clearInterval(timerId);
timerId = null;
timeLeft = 0;
pausedTime = 0;
updateDisplay();
}
}

function updateDisplay() {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
document.getElementById("display").textContent = `${minutes}:${seconds.toString().padStart(2, "0")}`;
}

function playSound() {
const audio = new Audio("timer.mp3");
audio.loop = true;
audio.play();
}
</script>
</body>
</html>
このコードを実行して、タイムを入力して、スタートボタンを押して、そこで一時停止ボタンを押して、一時停止された状態で再開ボタンを押すと続きからタイマーが始まるようにしたいのですが、最初から担ってしまいます。どうしたらいいのでしょうか。教えてください。

質問者からの補足コメント

  • できれば実際のコードも教えていただきたいです。

      補足日時:2023/12/15 22:11
  • できればindex.htmlにそのまま貼り付けて使用することができるコード全体も教えていただきたいです。

      補足日時:2023/12/15 22:40

A 回答 (7件)

No.1 です。



================
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>タイマーアプリ</title>
<style>
form {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}

label {
font-size: 24px;
margin-bottom: 16px;
}

input {
font-size: 24px;
padding: 8px;
margin-bottom: 16px;
text-align: center;
}

button {
font-size: 24px;
padding: 8px 16px;
margin: 8px;
}

#display {
font-size: 48px;
margin-bottom: 16px;
}
</style>
</head>
<body>
<form>
<label for="time">タイマーの長さ(秒):</label>
<input type="number" id="time" name="time" min="1" required>
<button id="start" onclick="startTimer(event)">スタート</button>
<button id="pause" onclick="pauseTimer(event)">一時停止</button>
<button id="reset" onclick="resetTimer()">リセット</button>
</form>

<div id="display">0:00</div>

<script>
let timeLeft = 0;
let timerId = null;
let pausedTime = 0;

function startTimer(event) {
event.preventDefault();
if (timerId !== null) {
return;
}
/*** ↓↓↓この辺を変えた↓↓↓ ***/
// timeLeft = parseInt(document.getElementById("time").value);
if (pausedTime == 0) {
timeLeft = parseInt(document.getElementById("time").value);
} else {
timeLeft = pausedTime
}
/*** ↑↑↑この辺を変えた↑↑↑ ***/

timerId = setInterval(() => {
timeLeft--;
if (timeLeft === 0) {
clearInterval(timerId);
timerId = null;
//playSound();
}
updateDisplay();
}, 1000);
}

function pauseTimer(event) {
event.preventDefault();
if (timerId !== null) {
clearInterval(timerId);
timerId = null;
pausedTime = timeLeft;
document.getElementById("pause").textContent = "再開";
} else {
timeLeft = pausedTime;
startTimer(event);
document.getElementById("pause").textContent = "一時停止";
}
}

function resetTimer() {
if (confirm("本当にリセットしますか?")) {
clearInterval(timerId);
timerId = null;
timeLeft = 0;
pausedTime = 0;
updateDisplay();
}
}

function updateDisplay() {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
document.getElementById("display").textContent = `${minutes}:${seconds.toString().padStart(2, "0")}`;
}

function playSound() {
const audio = new Audio("timer.mp3");
audio.loop = true;
audio.play();
}
</script>
</body>
</html>
================
    • good
    • 0
この回答へのお礼

ありがとうございます。
解決しました。

お礼日時:2023/12/18 18:03

こんな感じでしょうか。



<form>
<div id="display">0:00</div>
<label for="time">タイマーの長さ(秒):</label>
<input type="number" id="time" name="time" min="1" required>
<button id="start" onclick="startTimer(event)">スタート</button>
<button id="reset" onclick="resetTimer(event)">リセット</button>
</form>
<script>
const timer = {
_start: document.getElementById("start"),
_display: document.getElementById("display"),
_reset: document.getElementById("reset"),
left: 0,
id: null,
on () {
this._start.textContent = "一時停止";
this.display(this.left);
const start = Date.now();
const left = this.left;
this.id = setInterval(()=>{
this.left = left - (Date.now() - start) / 1000;
if(this.left < 0) {
this.reset();
}
this.display(this.left);
}, 100);
},
off(){
clearInterval(this.id);
this.id = null;
this._start.textContent = "再開";
},
reset () {
clearInterval(this.id);
this.id = null;
this._start.textContent = "スタート";
this.left = 0;
this.display(0);
},
display (left) {
left = Math.ceil(left);
const m = Math.floor(left / 60);
const s = (left % 60).toString().padStart(2, '0');
this._display.textContent = `${m}:${s}`;
}
}
function startTimer(event) {
event.preventDefault();
timer.left = (timer.left === 0) ? parseInt(document.getElementById("time").value) : timer.left;
if(timer.id){
timer.off();
}else {
timer.on();
}
}

function resetTimer(event) {
event.preventDefault();
if (confirm("本当にリセットしますか?")) {
timer.reset();
}
}
</script>
    • good
    • 0

こんばんは



>再開ボタンを押すと続きからタイマーが始まるようにしたいのですが、
>最初から担ってしまいます。
再開時の pauseTimer の処理内で、
>timeLeft = pausedTime;
>startTimer(event);
と timeLeft に値を戻しているつもりのようですが(実際には、この処理には意味がなさそうですが)、その後で startTimer を呼び出しているので、そちらで値が初期値にリセットされますよね?
>timeLeft = parseInt(document.getElementById("time").value);
ここの流れを修正すれば、ご希望の動作になると思います。


なお、以下はご質問には直接関係はありませんけれど・・・
一時停止中にも「スタート」は押せますが、その場合は最初からのカウントになりますね。
これは、予定通りの仕様でしょうか?

また、時間の計測が SetInterval の interval に依存する形式になっていますけれど、必ずしも正確とは言えません。(たいして誤差はないとは思いまが)
PCのタイマーを参照して、経過時間を計算するような方式にしておく方が、なんらかの遅延が生じた際にも、正確さを維持できることを期待できます。
    • good
    • 0

関数 startTimer の引数で区別しましょう


例)
startTimer(evnet, 設定秒数)
* スタートボタンの場合は time から読み込み値を設定秒数に指定
* 再開ボタンの場合は pausedTime の値を設定秒数に指定

余談ながら

setInterval の精度はあまりよろしくないので、
毎回の残秒数の計算は現在時刻から算出することをお勧めします。
例)
残秒数 = 設定秒数 - (現在時刻 - 開始時刻)
    • good
    • 0

pauseのイベントが二重で記述しているので正しく動きませんね。



停止するフラグを変数を追加して、その値によって停止か再開するかの分岐処理に変えましょう。
    • good
    • 0

No.1 です。

途中で送信してしまった。

startTimerで、pausedTimeが0の時は parseInt(document.getElementById("time").value) を、pausedTimeが0でないなら pausedTime をtimeLeftに入れる、とかですかね。
もっとスマートな方法はありそうですが、お手軽なのはこんな感じかと。
    • good
    • 0

再開したときに


> timeLeft = pausedTime;
で一時停止時の時間をtimeLeftに入れていますが、その後の
> startTimer(event);

> timeLeft = parseInt(document.getElementById("time").value);
とまた元の指定値を入れているからですね。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A