フロントエンジニアになるための練習問題 押すと色が変わるボタン7

前回の続きです。

課題

クライアントから追加の修正依頼がきました。

  • 色を変える時は、一つ前の色以外の色にして欲しい

グレーからは、赤・青・黄のどれかにランダムで変わるようにしましたが、連続で同じ色になることを防いで欲しい、という内容です。

具体的にいうと以下のようなことを指します。

  • グレーボタンをクリック
  • 赤色になる
  • 赤色のボタンをクリック
  • グレーになる
  • グレーボタンをクリック
  • 赤色以外(つまり青色か黄色)の色になる

前提

  • javascriptのループ処理を使える

30分から1時間程度。

実装の流れ

  • 一つ前に使われた色を記憶しておく
  • 色を取得する際には、一つ前に使われた色と違う色になるまで繰り返す

実装例

まずは、使われた色を記憶するために、適用したクラス名を保管する変数を定義し、クラスを適用した後にそのクラスを保管します。

prevColor という変数を宣言し、prevColor = applyClass; で適用したクラスをセットします。

//略

     let prevColor = ''; //追加

//略

        startButtonEl.addEventListener("click", () => {
          // 略

          if(startButtonEl.classList.contains("red-active") || startButtonEl.classList.contains("blue-active") || startButtonEl.classList.contains("yellow-active")){
            startButtonEl.classList.remove("red-active", "blue-active", "yellow-active");
          }else{
            const value = getRandom(1, 3);
            const applyClass = getClass(value);
            startButtonEl.classList.add(applyClass);
            prevColor = applyClass; //追加
          }
        });

続いて、色が異なるまでランダムに取得し続ける関数を作ります。

        const getDifferentClass = (prev) => {
          let result;

          while(true){
            result = getClass(getRandom(1, 3));
            if(result !== prev) break;
          }

          return result
        };

引数のprev には、前の色(クラス名)を渡します。

whileループはtrueなので無限にループし続けますが、ランダムで取得したクラス名とprevが異なれば break してループを抜けます。

全体のコードです。

        const getRandom = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);

        const getClass = (value) => {
          switch (value) {
            case 1: {
              return 'red-active';
            }
            case 2: {
              return 'blue-active';
            }
            case 3: {
              return 'yellow-active';
            }
          }
        };

        const getDifferentColor = (prev) => {
          let result;

          while(true){
            result = getClass(getRandom(1, 3));
            if(result !== prev) break;
          }

          return result;
        };


        let canClick = true;
        let prevColor = '';
        const startButtonEl = document.getElementById("start-button");

        startButtonEl.addEventListener("click", () => {
          const inactiveButton = () => {
            canClick = false;
            startButtonEl.innerText = '処理中...';
          };

          const activeButton = () => {
            canClick = true;
            startButtonEl.innerText = 'ボタン';
          };

          if(!canClick) return;

          inactiveButton();

          setTimeout(() => {
            activeButton();
          }, 5000);

          if(startButtonEl.classList.contains("red-active") || startButtonEl.classList.contains("blue-active") || startButtonEl.classList.contains("yellow-active")){
            startButtonEl.classList.remove("red-active", "blue-active", "yellow-active");
          }else{
            const applyClass = getDifferentColor(prevColor);
            startButtonEl.classList.add(applyClass);
            prevColor = applyClass;
          }
        });