一度動いたタイマーを止められないので一時停止機能を追加します
この部分では記載したはずの一時停止タイマーが出力されない、タスク終了後休憩タイマーに遷移しなかったりと大変でした
1. data
オプションに一時停止の状態とボタンの表示を制御する変数を追加します。
JavaScript
data() {
return {
minutes: 0,
seconds: 10,
breakMinutes: 0,
breakSeconds: 10,
breakTimerStartButton: false, //「作業時間」が終了し、タイマー関連の UI 要素を表示・非表示するためのフラグ
breakTimerDisplay: false,
remainingWorkSeconds: 25 * 60, // 作業残り時間(秒)
remainingBreakSeconds: 5 * 60, // 休憩残り時間(秒)
isWorkTimerActive: false, // 作業タイマーがアクティブかどうか
isBreakTimerActive: false, // 休憩タイマーがアクティブかどうか
isWorkTimerPaused: false, // 作業タイマーが一時停止中かどうか
isBreakTimerPaused: false, // 休憩タイマーが一時停止中かどうか
timerInterval: null, // タイマーのインターバルID
currentTimerLabel: "作業時間", // 現在のタイマーのラベル
};
},
解説:
isWorkTimerPaused
: 作業タイマーが一時停止中かどうかを示す真偽値です。初期値はfalse
です。isBreakTimerPaused
: 休憩タイマーが一時停止中かどうかを示す真偽値です。初期値はfalse
です。
2. タイマーを一時停止・再開するメソッド (pauseTimer
, resumeTimer
) を methods
オプションに追加します。
JavaScript
methods: {
toggleTimer(timerType) {
console.log(
"toggleTimer が呼び出されました:",
timerType,
this.isWorkTimerActive,
this.isBreakTimerActive
);
if (timerType === "work") {
if (!this.isWorkTimerActive) {
this.startWorkTimerInternal(); // 作業タイマー開始処理
} else {
this.pauseTimer("work"); // 作業タイマー一時停止
}
} else if (timerType === "break") {
if (!this.isBreakTimerActive) {
this.startBreakTimerInternal(); // 休憩タイマー開始処理
} else {
this.pauseTimer("break"); // 休憩タイマー一時停止
}
}
console.log(
"toggleTimer 終了:",
this.isWorkTimerActive,
this.isBreakTimerActive,
this.isWorkTimerPaused,
this.isBreakTimerPaused
);
},
startWorkTimerInternal() {
this.isWorkTimerActive = true;
this.isWorkTimerPaused = false;
this.currentTimerLabel = "作業時間";
this.remainingWorkSeconds = this.minutes * 60 + this.seconds;
this.timerInterval = setInterval(() => {
if (!this.isWorkTimerPaused) {
if (this.remainingWorkSeconds > 0) {
this.remainingWorkSeconds--;
} else {
this.stopTimerInterval();
this.isWorkTimerActive = false;
this.isWorkTimerPaused = false;
this.sendTimerEndStatus("work");
alert("作業時間終了!休憩を開始してください。");
this.startBreakTimerInternal();
}
}
}, 1000);
},
startBreakTimerInternal() {
this.isBreakTimerActive = true;
this.isBreakTimerPaused = false;
this.currentTimerLabel = "休憩時間";
this.remainingBreakSeconds = this.breakMinutes * 60 + this.breakSeconds;
this.timerInterval = setInterval(() => {
if (!this.isBreakTimerPaused) {
if (this.remainingBreakSeconds > 0) {
this.remainingBreakSeconds--;
} else {
this.stopTimerInterval();
this.isBreakTimerActive = false;
this.isBreakTimerPaused = false;
this.sendTimerEndStatus("break");
alert("休憩時間終了!");
// 必要に応じて作業タイマーを再開する処理を追加
}
}
}, 1000);
},
pauseTimer(timerType) {
console.log(
"pauseTimer が呼び出されました:",
timerType,
this.timerInterval
);
if (this.timerInterval) {
this.stopTimerInterval();
if (timerType === "work") {
this.isWorkTimerPaused = true;
} else if (timerType === "break") {
this.isBreakTimerPaused = true;
}
}
console.log(
"pauseTimer 終了:",
this.isWorkTimerPaused,
this.isBreakTimerPaused,
this.timerInterval
);
},
resumeTimer(timerType) {
if (!this.timerInterval) {
if (
timerType === "work" &&
this.isWorkTimerPaused &&
this.isWorkTimerActive
) {
this.isWorkTimerPaused = false;
this.timerInterval = setInterval(() => {
if (this.remainingWorkSeconds > 0) {
this.remainingWorkSeconds--;
} else {
this.stopTimerInterval();
this.isWorkTimerActive = false;
this.isWorkTimerPaused = false;
this.sendTimerEndStatus("work");
alert("作業時間終了!休憩を開始してください。");
this.startBreakTimer();
}
}, 1000);
} else if (
timerType === "break" &&
this.isBreakTimerPaused &&
this.isBreakTimerActive
) {
this.isBreakTimerPaused = false;
this.timerInterval = setInterval(() => {
if (this.remainingBreakSeconds > 0) {
this.remainingBreakSeconds--;
} else {
this.stopTimerInterval();
this.isBreakTimerActive = false;
this.isBreakTimerPaused = false;
this.sendTimerEndStatus("break");
alert("休憩時間終了!");
// 必要に応じて作業タイマーを再開する処理を追加
}
}, 1000);
}
}
},
stopTimerInterval() {
clearInterval(this.timerInterval);
this.timerInterval = null;
},
sendTimerEndStatus(status) {
const timerStatus = {
status: status,
endTime: new Date().toISOString(),
};
axios
.post("http://localhost:8080/api/timer-status", timerStatus) // バックエンドのエンドポイントに合わせて変更
.then((response) => {
console.log("タイマー終了ステータス送信成功", response.data);
})
.catch((error) => {
console.error("タイマー終了ステータス送信失敗", error);
});
},
},
};
解説:
startTimer()
とstartBreakTimer()
: タイマーがアクティブな場合はpauseTimer()
を呼び出すように変更しました。開始時には一時停止状態を解除します。pauseTimer(timerType)
:setInterval()
で設定されたタイマーをclearInterval()
で停止し、timerInterval
をnull
に設定します。引数timerType
に応じて、作業タイマーまたは休憩タイマーの一時停止状態をtrue
に設定します。resumeTimer(timerType)
:timerInterval
がnull
の場合(タイマーが停止している場合)、引数timerType
に応じて作業タイマーまたは休憩タイマーを再開します。一時停止状態をfalse
に戻し、setInterval()
を再度設定してカウントダウンを再開します。
3. <template>
部分に一時停止/再開ボタンを追加します。
HTML
<template>
<div>
<h1>ポモドーロタイマー</h1>
<div>
<label for="minutes">分:</label>
<input type="number" id="minutes" v-model="minutes" min="0" max="59" />
<input type="range" v-model="minutes" min="0" max="59" />
</div>
<div>
<label for="seconds">秒:</label>
<input type="number" id="seconds" v-model="seconds" min="0" max="59" />
<input type="range" v-model="seconds" min="0" max="59" />
</div>
<p>
{{ currentTimerLabel }}:
{{
currentTimerLabel === "作業時間" ? formattedTime : formattedBreakTime
}}
</p>
<button @click="toggleTimer('work')" :disabled="isBreakTimerActive">
{{ isWorkTimerActive ? "一時停止" : "開始" }}
</button>
<button
v-if="isWorkTimerActive"
@click="resumeTimer('work')"
:disabled="!isWorkTimerPaused"
>
再開
</button>
<div v-if="breakTimerStartButton">
<h2>休憩タイマー</h2>
<div>
<label for="breakMinutes">分:</label>
<input
type="number"
id="breakMinutes"
v-model="breakMinutes"
min="0"
max="59"
/>
<input type="range" v-model="breakMinutes" min="0" max="59" />
</div>
<div>
<label for="breakSeconds">分:</label>
<input
type="number"
id="breakSeconds"
v-model="breakSeconds"
min="0"
max="59"
/>
<input type="range" v-model="breakSeconds" min="0" max="59" />
</div>
<p>休憩時間:{{ formattedBreakTime }}</p>
<button @click="toggleTimer('break')" :disabled="isWorkTimerActive">
{{ isBreakTimerActive ? "一時停止" : "休憩開始" }}
</button>
<button
v-if="isBreakTimerActive"
@click="resumeTimer('break')"
:disabled="!isBreakTimerPaused"
>
休憩再開
</button>
</div>
<p v-if="breakTimerDisplay">休憩時間終了</p>
</div>
</template>
解説:
- 作業タイマーの「開始」ボタンのテキストを、アクティブな場合は「一時停止」に切り替えるようにしました。
- 作業タイマーがアクティブな場合にのみ表示される「再開」ボタンを追加しました。一時停止中でない場合は非活性になります。
- 休憩タイマーにも同様に「一時停止」と「再開」ボタンを追加しました。
上記を行なったことで
タスク実行中に一時停止ボタンが出力され、機能もした
しかし休憩中には一時停止のボタンが出力されないため追加作業を行う

修正箇所:
<template>
部分の休憩タイマーの開始ボタンと一時停止ボタンの表示条件を修正します。
現在のコード:
HTML
<button @click="toggleTimer('break')" :disabled="isWorkTimerActive">
{{ isBreakTimerActive ? "一時停止" : "休憩開始" }}
</button>
<button
v-if="isBreakTimerActive"
@click="resumeTimer('break')"
:disabled="!isBreakTimerPaused"
>
休憩再開
</button>
修正後のコード:
HTML
<button @click="toggleTimer('break')" :disabled="isWorkTimerActive">
{{ isBreakTimerActive && !isBreakTimerPaused ? "一時停止" : "休憩開始" }}
</button>
<button
v-if="isBreakTimerActive && isBreakTimerPaused"
@click="resumeTimer('break')"
:disabled="false"
>
休憩再開
</button>
修正後の結果と解説:
- 休憩開始/一時停止ボタンの修正: HTML
<button @click="toggleTimer('break')" :disabled="isWorkTimerActive"> {{ isBreakTimerActive && !isBreakTimerPaused ? "一時停止" : "休憩開始" }} </button>
@click="toggleTimer('break')"
: ボタンをクリックすると、toggleTimer
メソッドが'break'
を引数として呼び出されます。このメソッド内で、休憩タイマーの開始と一時停止の処理が行われます。:disabled="isWorkTimerActive"
: 作業タイマーがアクティブな間は、休憩タイマーの操作ボタンを非活性にします。{{ isBreakTimerActive && !isBreakTimerPaused ? "一時停止" : "休憩開始" }}
:- 休憩タイマーがアクティブ (
isBreakTimerActive
がtrue
) かつ 一時停止中でない (!isBreakTimerPaused
がtrue
) 場合、「一時停止」と表示します。 - 上記以外の状態(非アクティブまたは一時停止中)の場合は、「休憩開始」と表示します。これにより、休憩タイマーが開始されるとボタンの表示が「一時停止」に切り替わります。
- 休憩タイマーがアクティブ (
上記を行なっても解消されず
下2行を編集
startWorkTimerInternal() {
this.isWorkTimerActive = true;
this.isWorkTimerPaused = false;
this.currentTimerLabel = "作業時間";
this.remainingWorkSeconds = this.minutes * 60 + this.seconds;
this.timerInterval = setInterval(() => {
if (!this.isWorkTimerPaused) {
if (this.remainingWorkSeconds > 0) {
this.remainingWorkSeconds--;
} else {
this.stopTimerInterval();
this.isWorkTimerActive = false;
this.isWorkTimerPaused = false;
this.sendTimerEndStatus("work");
alert("作業時間終了!休憩を開始してください。");
this.breakTimerStartButton = true; // ← ここを追加
// this.startBreakTimerInternal(); // 自動開始ではなくボタン表示
}
}
}, 1000);
},
結果的には以下のように連動して動いてしまうタイマーが生成される

何度か編集しても表示されてしまうため
それぞれの状態をまとめてみることにした
https://suyasuyahirohiro.com/?p=172
その結果以下のように一時停止もうまく作動するようになった