PR

JavaScript初心者が独学で「今日のメニュー提案アプリ」を作ってみた

【広告】

HTML・CSS・JavaScriptを勉強して、コンピュータが食事メニューを提案するアプリを作りました。
条件分岐、配列の並べ替え、クラスの追加・削除などの機能を使っています。

このアプリは、何食べようか決められないときに使います。
提案されたメニューが気に入らないときは、「イヤだ」と言うと、違うメニューを提案してくれます。

そんなに便利でもないのですが、プログラミングを勉強して何かを作ることが目的です。
アプリの作り方の解説もあります。

メニュー提案アプリを使ってみよう

  • 「いいね」ボタンを押せばメニュー決定、「イヤだ」ボタンを押すと次のメニューを提案
  • 10回連続「イヤだ」を押すと「自分で決めて!!」と言われる
  • 「もう一回」ボタンを押すと初期状態に戻る

HTMLをチェック

HTMLでウェブページのコンテンツの構造を定義しています。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>今日何食べる?</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div class="container">
      <h1>今日何食べる?</h1>
      <button id="startBtn" class="startBtn">メニューを提案</button>

      <div id="resultArea" class="resultArea">
        <h2 id="menuText"></h2>
        <div id="btns" class="btns hide">
          <button id="okBtn" class="okBtn">いいね</button>
          <button id="changeBtn" class="changeBtn">イヤだ</button>
        </div>
      </div>

      <button id="resetBtn" class="resetBtn hide">もう一回</button>
    </div>

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

「メニューを提案ボタン」を押すとメニューが表示される仕組みはJavaScriptで設定します。

<h2 id="menuText"></h2>

👆こちらにメニューが表示されます。今は空になってます。

<div id="btns" class="btns hide">

このように、class に hide が付いている部分は、CSSを使って非表示にします。
現時点では見えている状態です。

HTMLだけではかなり地味な状態になっています。
ボタンを押しても何も起こりません。

メニューを1つ表示させる

app.js に以下のコードを書きました。
メニューを提案ボタンを押すと「ラーメン」と表示されます。

const menus = [
  'ラーメン',
  '牛丼',
  '天ぷら',
  'うどん',
  'カレー',
  'とんかつ',
  'そば',
  'お好み焼き',
  '寿司',
  'ハンバーガー',
];

const startBtn = document.getElementById('startBtn');
const menuText = document.getElementById('menuText');

let menuIndex = 0;

startBtn.addEventListener('click', () => {
  menuIndex = 0;
  menuText.textContent = menus[menuIndex];
});
  • 提案するメニューを配列で用意
  • 「メニューを提案」ボタンをクリックすると、<h2 id=”menuText”></h2> の部分にmenus[menuIndex] が表示される
  • menuIndex = 0; なので、menus[0]
  • 配列は0から数えるので、menus[0] はラーメン

「いいね」を押した場合

ラーメン食べたいなと思ったら「いいね」ボタンを押しましょう。
「ラーメン に決定!」と表示されます。

const okBtn = document.getElementById('okBtn');

okBtn.addEventListener('click', () => {
  menuText.textContent = menus[menuIndex] + ' に決定!';
});
  • 現在の menus[menuIndex] がラーメン
  • ラーメンの後ろに「 に決定!」を付ける

「イヤだ」を押した場合

「イヤだ」ボタンを押したら次のメニューが表示されます。

ラーメン → 牛丼 → 天ぷら → … → ハンバーガー

最後のハンバーガーまで行った場合は「自分で決めて!!」と表示されます。

const changeBtn = document.getElementById('changeBtn');

changeBtn.addEventListener('click', () => {
  menuIndex++;
  if (menuIndex >= menus.length) {
    menuText.textContent = '自分で決めて!!';
  } else {
    menuText.textContent = menus[menuIndex];
  }
});
  • menuIndex++; で次のメニューに変わる
  • menus.length は、配列の要素の数で、今回は10
  • menuIndex は、0から始まるので、最後のハンバーガーは、menus[9]
  • menus[10] 以上は「自分で決めて!!」になる

if else で条件分岐をしています。
もし10以上なら「自分で決めて!!」、それ以外なら番号が指定するメニューを表示。

if文の使い方の解説はこちら

「もう一回」ボタンでリセット

「もう一回」ボタンを押すと、menuIndex が0になり、メニューが表示されなくなります。
リセットした後に「メニューを提案」ボタンを押すと、ラーメンが表示されます。

const resetBtn = document.getElementById('resetBtn');

resetBtn.addEventListener('click', () => {
  menuIndex = 0;
  menuText.textContent = '';
});

配列をシャッフルしよう

これでメニューを順番に提案する機能は完成です。
でも、いつも同じ順番では面白くないので、メニューをシャッフルします。

function shuffleArray(ary) {
  let len = ary.length;
  while (len) {
    let i = Math.floor(Math.random() * len);
    let last = ary[--len];
    ary[len] = ary[i];
    ary[i] = last;
  }
}

👆こちらが配列をシャッフルする関数です。意味不明ですね。とりあえずコピペです。

この関数を「メニューを提案」ボタンを押すと実行します。
startBtn.addEventListener(‘click’, () => { の中にコードを追加します。

startBtn.addEventListener('click', () => {
  menuIndex = 0;

  // この1行を追加
  shuffleArray(menus);

  menuText.textContent = menus[menuIndex];
});

順番が毎回変わってますね。楽しいですね。

配列をランダムに並べ替える方法の解説はこちら

ボタンの表示・非表示を切り替え

ボタンのスタイルに display: none; を追加すると非表示になります。

初期状態

「いいね」「いやだ」「もう一回」の3つのボタンを初期状態では非表示にします。

HTMLの hide という class が付いている部分を消します。

<div id="btns" class="btns hide">
  <button id="okBtn" class="okBtn">いいね</button>
  <button id="changeBtn" class="changeBtn">イヤだ</button>
</div>

<button id="resetBtn" class="resetBtn hide">もう一回</button>

.hide をCSSで非表示にします。

.btns.hide {
  display: none;
}

.resetBtn.hide {
  display: none;
}

上の方は、btns と hide の両方のクラスがついている要素を非表示にするという意味です。
下の方は、resetBtn と hide の両方のクラスです。

3つのボタンが消えました。

「メニューを提案」ボタンを押したとき

「メニューを提案」ボタンを消して、「いいね」「イヤだ」を表示します。

CSS に次を追加します。

.startBtn.hide {
  display: none;
}

js の startBtn を押したときの処理に次のコードを追加します。
classを付けたり外したりするコードです。

// まず、こちらを追加
const btns = document.getElementById('btns');

startBtn.addEventListener('click', () => {
  menuIndex = 0;

  // 以下の2行を追加
  startBtn.classList.add('hide');
  btns.classList.remove('hide');

  shuffleArray(menus);
  menuText.textContent = menus[menuIndex];
});

add が付けるで、remove が外すですね。

「メニューを提案」が消えて、「いいね」「イヤだ」が出てきました。

「もう一回」ボタンを表示する

「いいね」を押したときと、「自分で決めて!!」が表示されたときに、「いいね」「イヤだ」ボタンを消して、「もう一回」ボタンを表示させます。

okBtn.addEventListener('click', () => {
  menuText.textContent = menus[menuIndex] + ' に決定!';

  // 以下の2行を追加
  btns.classList.add('hide');
  resetBtn.classList.remove('hide');
});

changeBtn.addEventListener('click', () => {
  menuIndex++;
  if (menuIndex >= menus.length) {
    menuText.textContent = '自分で決めて!!';

    // 以下の2行を追加
    btns.classList.add('hide');
    resetBtn.classList.remove('hide');

  } else {
    menuText.textContent = menus[menuIndex];
  }
});

「もう一回」が表示されて、「いいね」「イヤだ」が消えました。

「もう一回」ボタンで初期状態の戻す

「もう一回」ボタンを押すと、「もう一回」ボタンが消えて、「メニューを提案」ボタンが表示されます。

resetBtn.addEventListener('click', () => {
  menuIndex = 0;
  menuText.textContent = '';

  // 以下の2行を追加
  resetBtn.classList.add('hide');
  startBtn.classList.remove('hide');
});

JavaScriptはこれで完成です。
コードをわかりやすく並べ替えた完成版はこちらです。

const menus = [
  'ラーメン',
  '牛丼',
  '天ぷら',
  'うどん',
  'カレー',
  'とんかつ',
  'そば',
  'お好み焼き',
  '寿司',
  'ハンバーガー',
];

// HTML要素の定数定義
const startBtn = document.getElementById('startBtn');
const menuText = document.getElementById('menuText');
const btns = document.getElementById('btns');
const okBtn = document.getElementById('okBtn');
const changeBtn = document.getElementById('changeBtn');
const resetBtn = document.getElementById('resetBtn');

// 状態管理のための変数
let menuIndex = 0;

// ユーティリティ関数
function shuffleArray(ary) {
  let len = ary.length;
  while (len) {
    let i = Math.floor(Math.random() * len);
    let last = ary[--len];
    ary[len] = ary[i];
    ary[i] = last;
  }
}

// イベントリスナー
startBtn.addEventListener('click', () => {
  menuIndex = 0;

  startBtn.classList.add('hide');
  btns.classList.remove('hide');

  shuffleArray(menus);
  menuText.textContent = menus[menuIndex];
});

okBtn.addEventListener('click', () => {
  menuText.textContent = menus[menuIndex] + ' に決定!';

  btns.classList.add('hide');
  resetBtn.classList.remove('hide');
});

changeBtn.addEventListener('click', () => {
  menuIndex++;
  if (menuIndex >= menus.length) {
    menuText.textContent = '自分で決めて!!';

    btns.classList.add('hide');
    resetBtn.classList.remove('hide');
  } else {
    menuText.textContent = menus[menuIndex];
  }
});

resetBtn.addEventListener('click', () => {
  menuIndex = 0;
  menuText.textContent = '';

  resetBtn.classList.add('hide');
  startBtn.classList.remove('hide');
});

CSSでデザインを改善する

アプリとしてはこれで完成しました。
しかし、あまりにもダサすぎるので、CSSでデザインをしました。

以下のコードをコピペしてください。
まだ微妙なデザインですが、かなりマシになっているはずです。

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  width: 100%;
  height: 100vh;
  font-family: sans-serif;
  background-color: #fbf7ee;
  font-size: 16px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.container {
  width: 90%;
  max-width: 600px;
  height: 500px;
  background-color: #fff;
  border: 10px solid #f77f00;
  border-radius: 10px;
  box-shadow: 2px 2px 4px #666;
  padding: 20px;
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
h1 {
  font-size: 2rem;
  margin-bottom: 40px;
}
h2 {
  font-size: 2rem;
  margin-bottom: 40px;
}
.btns {
  display: flex;
  justify-content: center;
  gap: 12px;
}
button {
  font-size: 1.4rem;
  padding: 10px 20px;
  border-radius: 5px;
  border: none;
  cursor: pointer;
  margin: 5px;
}
.startBtn,
.resetBtn {
  background-color: #0d6efd;
  color: #fff;
}
.okBtn {
  background-color: #198754;
  color: #fff;
}
.changeBtn {
  background-color: #dc3545;
  color: #fff;
}
.startBtn.hide {
  display: none;
}
.btns.hide {
  display: none;
}
.resetBtn.hide {
  display: none;
}

実は、ボタンの色などChatGPTに考えてもらったところもあります。
自力で考えると変な色を選んでしまいます。AIなら最悪は避けられるので、利用してもいいのではないでしょうか。

Flexbox を使えば簡単に中央寄せができます。

 display: flex;
 justify-content: center;
 align-items: center;

Flexboxで要素を完璧に上下左右中央寄せする3行コードはこちら

ボタンはおしゃれになってますね。ちょっとシンプルすぎるかもしれませんが。

ボタンデザインにこだわりたい方は、以下のページをチェック。
コピペでおしゃれなボタンが使えます。

🔵 CSSで作るおしゃれな青のボタン6パターン

🔴 CSSで作るおしゃれな赤のボタン6パターン

🟢 CSSで作るおしゃれな緑のボタン6パターン

おわりに

JavaScript初心者が作った作品を紹介しました。少し勉強すればこれくらいはできるようになるという目安にしていただければ幸いです。

このアプリ自体そんなに使い道がないですが、カスタマイズすれば面白いアプリに変身するかもしれません。

本を見ながら勉強するのもいいですが、簡単なアプリを自分で作ってみる方が理解が進むと思います。この記事を参考にして、自分で何か作ってみてください。

初心者向けに細かく解説しましたが、HTML・CSSもあまりわからない、JavaScriptは全然わからないという方には難しかったと思います。

完全初心者の方には、動画学習サービスのUdemyで、HTML・CSS・JavaScriptの基礎を学ぶことをおすすめします。

私が受講した講座の体験談を書いているので参考にしてください👇

Udemy Web開発講座 受講体験:難しかった点と私が作ったアプリ

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