JavaScript | 1 日 60 分 × 7 日アプリ学習:JavaScript基礎・DOM操作 サイコロ編

Web APP JavaScript
スポンサーリンク
スポンサーリンク

7日目のゴールと全体像

サイコロアプリ 7日目のテーマは 「6日間で積み上げてきた機能を“完成版”として整理し、アプリ全体の構造を理解しながら総復習すること」 です。

ここまでで、みなさんは

  • 2つのサイコロの結果表示
  • 合計値の計算と背景色の変更
  • 履歴の保存・一覧表示・削除
  • 並び替え(新しい順・古い順)
  • 詳細表示・メモ編集・削除アニメーション

という、初級者が学ぶべき JavaScript の基礎をすべて体験してきました。

7日目では、これらを ひとつの完成したアプリとしてまとめる ことで、 「JavaScript初級者から Webアプリを作れる人」へステップアップします。

アプリ全体の構造を理解する

完成版のサイコロアプリは、次の3つのレイヤーで構成されています。

● HTML(画面の骨格)

  • ボタン
  • サイコロの結果表示
  • 合計値表示
  • メッセージ表示
  • 履歴一覧
  • 詳細表示エリア

● CSS(見た目・アニメーション)

  • 背景色変更
  • 履歴カードのデザイン
  • 削除アニメーション
  • 詳細カードのデザイン

● JavaScript(動き・データ管理)

  • ランダム処理
  • DOM操作
  • イベント処理
  • ローカルストレージ
  • 履歴管理(追加・削除・編集)
  • 並び替え
  • 詳細表示

この3つが組み合わさることで、 「入力 → 計算 → 表示 → 保存 → 編集 → 削除」 という一連の流れが成立します。

完成版HTML(最終形)

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>サイコロアプリ 完成版</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <h2>サイコロアプリ</h2>

  <button id="rollBtn">サイコロを振る</button>

  <p id="dice1">サイコロ1:ー</p>
  <p id="dice2">サイコロ2:ー</p>
  <p id="diceSum">合計:ー</p>
  <p id="diceMessage"></p>

  <h3>履歴</h3>
  <button id="sortNewBtn">新しい順</button>
  <button id="sortOldBtn">古い順</button>

  <div id="historyList"></div>

  <button id="clearHistoryBtn">履歴をすべて削除</button>

  <h3>詳細</h3>
  <div id="detailBox"></div>

  <script src="script.js"></script>
</body>
</html>

完成版CSS(最終形)

body {
  font-family: sans-serif;
  padding: 20px;
  transition: background-color 0.5s;
}

#dice1, #dice2, #diceSum {
  font-size: 20px;
  margin-top: 10px;
}

#diceMessage {
  font-size: 22px;
  margin-top: 15px;
  font-weight: bold;
}

.history-card {
  background: #fff;
  padding: 12px;
  margin: 10px 0;
  border-radius: 8px;
  box-shadow: 0 2px 5px rgba(0,0,0,0.1);
  transition: transform 0.2s, opacity 0.4s;
}

.history-card:hover {
  transform: scale(1.02);
}

.fade-out {
  opacity: 0;
  transform: translateY(-10px);
}

.detail-card {
  background: #fefefe;
  padding: 15px;
  margin-top: 15px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

完成版JavaScript(最終形)

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);
JavaScript

7日目で本当に掴んでほしいこと

● JavaScriptの基礎が「ひとつのアプリ」で全部つながった

  • 変数
  • 条件分岐
  • 繰り返し
  • 関数
  • DOM操作
  • イベント処理
  • ローカルストレージ

これらがすべて「サイコロアプリ」という具体的な形の中で自然につながっています。

● Webアプリは「画面 × 動き × データ」でできている

  • HTML → 画面
  • CSS → 見た目
  • JavaScript → 動き・データ管理

この3つを組み合わせることで、 どんなWebアプリでも作れるようになります。

● DOM操作はアプリの“手足”

カード追加、削除、編集、アニメーションなど、 DOMを自在に扱えるとアプリが一気に本格的になる。

次のステップ(応用編への橋)

このサイコロアプリはまだまだ育てられます。

  • 結果の統計(平均値・最大値など)
  • グラフ表示(結果の推移)
  • 履歴のCSVダウンロード
  • Webアプリ化(React / Vue)

初級編を終えたみなさんは、 もう 「JavaScriptで実用的なWebアプリを作れる人」 です。

タイトルとURLをコピーしました