6日目のゴールと全体像
サイコロアプリ 6日目のテーマは 「履歴カードを“編集・色分け・アニメーション付き削除”できるようにし、DOM操作の応用力をさらに引き上げること」 です。
ここまでで、みなさんは
- 2つのサイコロを振る
- 合計値を計算する
- 合計値に応じて背景色・メッセージを変える
- 履歴を保存・一覧表示・削除する
- 並び替え・詳細表示
という「データ管理ができるサイコロアプリ」を作ってきました。
6日目ではここに 編集機能・色分け強化・削除アニメーション を加えて、 より“使いやすく楽しい”アプリへ進化させます。
履歴カードに「メモ編集」機能を追加する
履歴に「メモ」を追加できると、 自分だけのサイコロ記録帳 として使えるようになります。
履歴オブジェクトに memo を追加する
const historyItem = {
dice1: n1,
dice2: n2,
sum: sum,
dateTime: dateTimeText,
message: msg,
memo: "", // 新しく追加
time: now.getTime()
};
JavaScript深掘りポイント
- メモは「ユーザーが自由に書ける情報」。
- オブジェクトにプロパティを追加するだけで機能拡張できる。
- データ構造を柔軟に扱えることが JavaScript の強み。
メモ編集ボタンをカードに追加する
card.innerHTML = `
<p>日時:${item.dateTime}</p>
<p>サイコロ1:${item.dice1}</p>
<p>サイコロ2:${item.dice2}</p>
<p>合計:${item.sum}</p>
<p>メッセージ:${item.message}</p>
<p>メモ:${item.memo || "なし"}</p>
<button class="history-detail-btn">詳細</button>
<button class="history-edit-btn">メモ編集</button>
<button class="history-delete-btn">削除</button>
`;
JavaScriptメモ編集処理を作る
function editMemo(index) {
const newMemo = prompt("メモを入力してください:");
if (newMemo === null) return; // キャンセル時
historyArray[index].memo = newMemo; // メモ更新
saveHistory(historyArray); // 保存
renderHistory(historyArray); // 再描画
}
JavaScript深掘りポイント
prompt()は簡易入力ダイアログ。- キャンセル時は
nullが返るため、必ず条件分岐で処理を止める。 - 「データを更新 → 保存 → 再描画」が一連の流れ。
カード色分け(合計値によって背景色を変える)
合計値が高いほど明るい色にするなど、 視覚的にわかりやすくします。
function getCardColor(sum) {
if (sum <= 4) return "#f8d7da"; // 赤
if (sum <= 8) return "#cce5ff"; // 青
return "#fff8b3"; // 金色
}
JavaScript深掘りポイント
- 色分けは「視覚的フィードバック」を強化する。
- 合計値の強さが直感的に伝わる。
- UIの質が上がるとアプリの満足度が大きく向上する。
削除アニメーションを追加する
削除時にカードがふわっと消えると、 アプリの使い心地が大きく向上します。
CSS(削除アニメーション)
.fade-out {
opacity: 0;
transform: translateY(-10px);
transition: opacity 0.4s, transform 0.4s;
}
JavaScript(削除処理)
function deleteHistory(index, cardElement) {
cardElement.classList.add("fade-out");
setTimeout(() => {
historyArray.splice(index, 1);
saveHistory(historyArray);
renderHistory(historyArray);
}, 400);
}
JavaScript深掘りポイント
.classList.add()でCSSアニメーションを適用。setTimeout()でアニメーション後に削除。- UIが滑らかになると「プロっぽいアプリ」になる。
履歴描画関数を強化する
function renderHistory(historyArray) {
const list = document.getElementById("historyList");
list.innerHTML = "";
historyArray.forEach((item, index) => {
const card = document.createElement("div");
card.className = "history-card";
card.style.backgroundColor = getCardColor(item.sum);
card.innerHTML = `
<p>日時:${item.dateTime}</p>
<p>サイコロ1:${item.dice1}</p>
<p>サイコロ2:${item.dice2}</p>
<p>合計:${item.sum}</p>
<p>メッセージ:${item.message}</p>
<p>メモ:${item.memo || "なし"}</p>
<button class="history-detail-btn">詳細</button>
<button class="history-edit-btn">メモ編集</button>
<button class="history-delete-btn">削除</button>
`;
card.querySelector(".history-detail-btn").addEventListener("click", function() {
showDetail(item);
});
card.querySelector(".history-edit-btn").addEventListener("click", function() {
editMemo(index);
});
card.querySelector(".history-delete-btn").addEventListener("click", function() {
deleteHistory(index, card);
});
list.appendChild(card);
});
}
JavaScript6日目の完成コード(script.js 全体)
const rollBtn = document.getElementById("rollBtn");
const dice1 = document.getElementById("dice1");
const dice2 = document.getElementById("dice2");
const diceSum = document.getElementById("diceSum");
const diceMessage = document.getElementById("diceMessage");
const clearHistoryBtn = document.getElementById("clearHistoryBtn");
const sortNewBtn = document.getElementById("sortNewBtn");
const sortOldBtn = document.getElementById("sortOldBtn");
let historyArray = loadHistory();
function rollDice() {
return Math.floor(Math.random() * 6) + 1;
}
function updateBackground(sum) {
if (sum <= 4) document.body.style.backgroundColor = "#f8d7da";
else if (sum <= 8) document.body.style.backgroundColor = "#cce5ff";
else document.body.style.backgroundColor = "#fff8b3";
}
function getSumMessage(sum) {
if (sum <= 4) return "今日は慎重にいきましょう。";
if (sum <= 8) return "まずまずの運勢。落ち着いて進めればOK。";
return "最高の運勢!何をしても楽しめそうです!";
}
function getCardColor(sum) {
if (sum <= 4) return "#f8d7da";
if (sum <= 8) return "#cce5ff";
return "#fff8b3";
}
function saveHistory(arr) {
localStorage.setItem("diceHistory", JSON.stringify(arr));
}
function loadHistory() {
const data = localStorage.getItem("diceHistory");
return data ? JSON.parse(data) : [];
}
function showDetail(item) {
const detailBox = document.getElementById("detailBox");
detailBox.innerHTML = `
<div class="detail-card">
<p>日時:${item.dateTime}</p>
<p>サイコロ1:${item.dice1}</p>
<p>サイコロ2:${item.dice2}</p>
<p>合計:${item.sum}</p>
<p>メッセージ:${item.message}</p>
<p>メモ:${item.memo || "なし"}</p>
</div>
`;
}
function editMemo(index) {
const newMemo = prompt("メモを入力してください:");
if (newMemo === null) return;
historyArray[index].memo = newMemo;
saveHistory(historyArray);
renderHistory(historyArray);
}
function deleteHistory(index, cardElement) {
cardElement.classList.add("fade-out");
setTimeout(() => {
historyArray.splice(index, 1);
saveHistory(historyArray);
renderHistory(historyArray);
}, 400);
}
function renderHistory(historyArray) {
const list = document.getElementById("historyList");
list.innerHTML = "";
historyArray.forEach((item, index) => {
const card = document.createElement("div");
card.className = "history-card";
card.style.backgroundColor = getCardColor(item.sum);
card.innerHTML = `
<p>日時:${item.dateTime}</p>
<p>サイコロ1:${item.dice1}</p>
<p>サイコロ2:${item.dice2}</p>
<p>合計:${item.sum}</p>
<p>メッセージ:${item.message}</p>
<p>メモ:${item.memo || "なし"}</p>
<button class="history-detail-btn">詳細</button>
<button class="history-edit-btn">メモ編集</button>
<button class="history-delete-btn">削除</button>
`;
card.querySelector(".history-detail-btn").addEventListener("click", function() {
showDetail(item);
});
card.querySelector(".history-edit-btn").addEventListener("click", function() {
editMemo(index);
});
card.querySelector(".history-delete-btn").addEventListener("click", function() {
deleteHistory(index, card);
});
list.appendChild(card);
});
}
rollBtn.addEventListener("click", function() {
const n1 = rollDice();
const n2 = rollDice();
const sum = n1 + n2;
dice1.textContent = `サイコロ1:${n1}`;
dice2.textContent = `サイコロ2:${n2}`;
diceSum.textContent = `合計:${sum}`;
updateBackground(sum);
const msg = getSumMessage(sum);
diceMessage.textContent = msg;
const now = new Date();
const dateTimeText =
`${now.getFullYear()}-${now.getMonth()+1}-${now.getDate()} ${now.getHours()}:${now.getMinutes()}`;
const historyItem = {
dice1: n1,
dice2: n2,
sum: sum,
dateTime: dateTimeText,
message: msg,
memo: "",
time: now.getTime()
};
historyArray.push(historyItem);
saveHistory(historyArray);
renderHistory(historyArray);
});
clearHistoryBtn.addEventListener("click", function() {
localStorage.removeItem("diceHistory");
historyArray = [];
renderHistory(historyArray);
});
sortNewBtn.addEventListener("click", function() {
historyArray.sort((a, b) => b.time - a.time);
renderHistory(historyArray);
});
sortOldBtn.addEventListener("click", function() {
historyArray.sort((a, b) => a.time - b.time);
renderHistory(historyArray);
});
renderHistory(historyArray);
JavaScript6日目で本当に掴んでほしいこと
● DOM操作は「画面を作り変える力」
カードUI、編集、削除、アニメーションなど、 DOMを自在に扱えるとアプリが一気に本格的になる。
● ローカルストレージ+編集機能で“記録アプリ”になる
履歴が残り、編集できることで、 サイコロアプリは「自分の運勢ログ」に進化する。
● イベント処理は複数組み合わせると強力
- click
- DOM追加
- ローカルストレージ保存
- アニメーション
これらが組み合わさると、 ユーザーが気持ちよく使えるアプリになる。
次のステップ(7日目)
7日目では、 アプリ全体を完成版として整理し、構造を最終調整する というステップへ進みます。
さらに深掘りしたい方は DOM操作の応用 や イベント処理の設計 を選ぶと理解がより強固になります。


