優美なタイマー
2025/5/22
現状の実行履歴のフォーマット
https://gyazo.com/92bde73ed0d28a4ee27212770684e2a5
Geminiが作ったものをそのまま使っている
時間表記などを少し変えたい
2025/5/20
https://gyazo.com/052af32a88d1d420a96b02654ea889b0
ブラウザのローカルストレージにlogを残しておくことに
2025/5/17
タスクの履歴を保存しておいて、入力時にサジェストが働くと嬉しいかも
2025/5/16
実行記録をログとしてファイルに記録していきたい
Webで公開しているバージョンはさすがに厳しいので(ローカルストレージを使う手はあるが)、自分のローカルで立ち上げているバージョンの機能とする。
ファイルへの書き込みは、Node.jsでやるか、PythonのCGIでやるか
PythonのCGIモジュールがそろそろ怪しいので、TextboxをNode.jsベースに書き換えようと考えていたが、その前段階としてこのタイマーアプリでやってみてもいいかもしれない
とりあえず、Geminiに相談してみよう
Node.jsでサーバーを立ち上げて、そこで動かすテスト。
npm initは不用と分かった。
2025/5/14
クリックしてから1秒まで「これ、ちゃんと動いている?」という気持ちになるのでアクションを加えた
2025/5/9
背景色を少し透明に
https://gyazo.com/bde8e94db1b612362701da8edae04da8
2025/5/8
ローカルサーバーで立ち上げたら、作業ログをファイルに保存していくこともできるな
背景画像はランダムで変更してもいいな(あるいは変更するボタンをつけるか)
和風なフォントを探す
「江戸文字」にぴったりな日本語フリーフォント|いいフォント
四季の詞~冬┃無料ダウンロード┃白舟書体 伝統的書体から遊び心溢れるデザイン筆文字のフォントまで
白舟楷書年賀
2025/5/7
rashita.netにアップロード
優美なタイマー
2025/5/5
Geminiに頼んで、タイマーアプリを作ってもらった。
倉下のアイデアで「和風」(実際は屏風)のイメージを加えてみた
https://gyazo.com/ad4ec181d965b82e66c07ac57f3078df
https://gyazo.com/be99c8daccfe246b4eacacbea2323936
このくらいのコードなら楽々書いてしまう。
code:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>優美なタイマー</title>
<style>
body {
font-family: 'Noto Sans JP', sans-serif;
margin: 0;
background-color: #f8f8f8;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.container {
background-color: #fff;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
padding: 40px;
text-align: center;
}
.background-image {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
z-index: -1;
}
h1 {
color: #333;
margin-bottom: 20px;
}
.task-input {
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ccc;
border-radius: 5px;
width: 300px;
font-size: 16px;
}
.timer {
font-family: 'Shippori Mincho B1', serif;
font-size: 3em;
color: #e47911; /* 伝統的な色合い */
margin-bottom: 20px;
}
.controls button {
padding: 10px 20px;
font-size: 16px;
border: none;
border-radius: 5px;
cursor: pointer;
margin: 0 10px;
}
.start-button {
background-color: #4CAF50;
color: white;
}
.stop-button {
background-color: #f44336;
color: white;
}
.reset-button {
background-color: #008CBA;
color: white;
}
.result {
margin-top: 30px;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #f9f9f9;
}
.hundred-poems {
margin-top: 20px;
font-style: italic;
color: #777;
}
</style>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&family=Shippori+Mincho+B1&display=swap" rel="stylesheet">
</head>
<body>
<img src="image/yukiko-kanada-iqmmtdW89n0-unsplash.jpg" alt="背景画像" class="background-image">
<div class="container">
<h1>優美なタイマー</h1>
<input type="text" id="task" class="task-input" placeholder="実行するタスクを入力">
<div class="timer" id="display">00:00:00</div>
<div class="controls">
<button id="startStop" class="start-button">開始</button>
<button id="reset" class="reset-button">リセット</button>
</div>
<div id="resultArea" class="result" style="display: none;">
<h2>終了</h2>
<p>タスク: <span id="completedTask"></span></p>
<p>実行時間: <span id="elapsedTime"></span></p>
<div class="hundred-poems" id="poem"></div>
</div>
</div>
<script>
let timerInterval;
let startTime;
let elapsedTime = 0;
const display = document.getElementById('display');
const startStopButton = document.getElementById('startStop');
const resetButton = document.getElementById('reset');
const taskInput = document.getElementById('task');
const resultArea = document.getElementById('resultArea');
const completedTaskElement = document.getElementById('completedTask');
const elapsedTimeElement = document.getElementById('elapsedTime');
const poemElement = document.getElementById('poem');
const hyakuninIsshu = [
"秋の田の かりほの庵の とまをあらみ わが衣手は 露にぬれつつ",
"春過ぎて 夏来にけらし 白妙の 衣ほすてふ 天の香具山",
"あしびきの 山鳥の尾の しだり尾の ながながし夜を ひとりかも寝む",
"田子の浦に うち出でて見れば 白妙の 富士のたかねに 雪は降りつつ",
"奥山に 紅葉踏み分け 鳴く鹿の 声聞く時ぞ 秋はかなしき",
// ... (百人一首 全首を記述することも可能ですが、ここでは省略します)
"夜をこめて 鳥の空音は はかるとも よに逢坂の 関は許さじ",
"今はただ 思ひ絶えなむ とばかり 人づてならで 言ふよしもがな",
"朝ぼらけ 有明の月と 見るまでに 吉野の里に 降れる白雪",
"わが袖は 潮干に見えぬ 沖の石の 人こそ知らね かわく間もなし",
"世の中は 常にもがもな 渚こぐ 海人の小舟の 綱手かなしも"
];
function formatTime(ms) {
const totalSeconds = Math.floor(ms / 1000);
const seconds = totalSeconds % 60;
const minutes = Math.floor(totalSeconds / 60) % 60;
const hours = Math.floor(totalSeconds / 3600);
return ${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')};
}
function updateTimer() {
const now = new Date().getTime();
elapsedTime = now - startTime;
display.textContent = formatTime(elapsedTime);
}
function startTimer() {
startTime = new Date().getTime();
timerInterval = setInterval(updateTimer, 1000);
startStopButton.textContent = '停止';
startStopButton.classList.remove('start-button');
startStopButton.classList.add('stop-button');
resultArea.style.display = 'none'; // 再度開始時に結果表示を消す
}
function stopTimer() {
clearInterval(timerInterval);
timerInterval = undefined; // タイマー停止時に timerInterval を undefined にする
startStopButton.textContent = '開始';
startStopButton.classList.remove('stop-button');
startStopButton.classList.add('start-button');
showResult();
}
function resetTimer() {
clearInterval(timerInterval);
timerInterval = undefined; // リセット時にも timerInterval を undefined にする
elapsedTime = 0;
display.textContent = '00:00:00';
startStopButton.textContent = '開始';
startStopButton.classList.remove('stop-button');
startStopButton.classList.add('start-button');
resultArea.style.display = 'none';
}
function showResult() {
const taskName = taskInput.value.trim();
completedTaskElement.textContent = taskName || '未入力';
elapsedTimeElement.textContent = formatTime(elapsedTime);
const randomIndex = Math.floor(Math.random() * hyakuninIsshu.length);
poemElement.textContent = hyakuninIsshurandomIndex;
resultArea.style.display = 'block';
}
startStopButton.addEventListener('click', () => {
if (!timerInterval) { // timerInterval が falsy (undefined または null) の場合のみ開始
startTimer();
} else {
stopTimer();
}
});
resetButton.addEventListener('click', resetTimer);
</script>
</body>
</html>