【问题标题】:JavaScript: Can't change the selected game modeJavaScript:无法更改选定的游戏模式
【发布时间】:2021-09-22 19:13:27
【问题描述】:

我正在尝试制作一个给定颜色的游戏,然后玩家必须选择正确的颜色。共有三种游戏模式:rgb、hex、hsl。我在顶部给出了三个按钮来更改当前的游戏模式。

更改游戏模式后,所问的问题必须更改为所选游戏模式的相同颜色代码。但是,即使问题的更改工作正常,选项中的颜色也会以与所选颜色代码相同的方式更改。由于我以某种方式默认selectedGameModergb,因此游戏运行器仅适用于rgb。而且即使在改变游戏模式后,游戏运行者仍然使用 rgb 作为选择的游戏模式。 当我点击一个按钮时,会执行以下操作:

let selectedGameMode = "rgb";
document.querySelectorAll(".colorCodeBtn").forEach((btn) => {
  btn.addEventListener("click", () => {
    if (btn.classList.contains("selectedColorCode")) return;
    btn.parentElement
      .querySelector(".selectedColorCode")
      .classList.remove("selectedColorCode");
    btn.classList.add("selectedColorCode");
    selectedGameMode = btn.getAttribute("game-mode");
    gameRunner();
  });
});
  1. 这里的colorCodeBtn 是用于更改游戏模式的按钮的类,如图所示,共有三个。
  2. 这里的selectedColorCode 是添加到所选按钮的类,并变为白色。
  3. 这里game-mode 是赋予这些按钮的属性,用于了解哪个按钮将游戏更改为哪个模式。
  4. gameRunner 是一个处理游戏中发生的一切的函数。

当我使用console.log() 显示当前选择的游戏模式时,它显示正确,这意味着它有效。

那么,这里可能有问题:

function randomColorGenerator() {
  let red = Math.round(Math.random() * 255);
  let green = Math.round(Math.random() * 255);
  let blue = Math.round(Math.random() * 255);
  if (selectedGameMode === "rgb") {
    return `rgb(${red}, ${green}, ${blue})`;
  } else if (selectedGameMode === "hex") {
    let hexRed = red.toString(16);
    let hexGreen = green.toString(16);
    let hexBlue = blue.toString(16);
    return `#${hexRed + hexGreen + hexBlue}`;
  } else if (selectedGameMode === "hsl") {
    let h = Math.round(Math.random() * 360);
    let s = Math.round(Math.random() * 100) + "%";
    let l = Math.round(Math.random() * 100) + "%";
    return `hsl( ${h}, ${s}, ${l})`;
  }
}

这是一个可以为我们生成随机颜色的函数。我已经多次测试了这个功能,它可以正常工作。那么,这里的 if 案例没有得到满足吗?如果不是,为什么因为 selectedGameMode 根据日志是正确的。这里的selectedGameMode 即使在更改之后仍然是 rgb。

非常感谢任何帮助!

这是我目前拥有的代码

let selectedGameMode = "rgb";
gameRunner();
document.querySelectorAll(".colorCodeBtn").forEach((btn) => {
  btn.addEventListener("click", () => {
    if (btn.classList.contains("selectedColorCode")) return;
    btn.parentElement
      .querySelector(".selectedColorCode")
      .classList.remove("selectedColorCode");
    btn.classList.add("selectedColorCode");
    selectedGameMode = btn.getAttribute("game-mode");
    gameRunner();
  });
});

function randomColorGenerator() {
  let red = Math.round(Math.random() * 255);
  let green = Math.round(Math.random() * 255);
  let blue = Math.round(Math.random() * 255);
  if (selectedGameMode == "rgb") {
    return `rgb(${red}, ${green}, ${blue})`;
  } else if (selectedGameMode == "hex") {
    let hexRed = red.toString(16);
    let hexGreen = green.toString(16);
    let hexBlue = blue.toString(16);
    return `#${hexRed + hexGreen + hexBlue}`;
  } else if (selectedGameMode == "hsl") {
    let h = Math.round(Math.random() * 360);
    let s = Math.round(Math.random() * 100) + "%";
    let l = Math.round(Math.random() * 100) + "%";
    return `hsl( ${h}, ${s}, ${l})`;
  }
}

function gameRunner() {
  let correctColor = randomColorGenerator();
  let randomNumber = Math.round(Math.random() * 6);
  document.querySelectorAll(".gameColorOption").forEach((btn) => {
    btn.style.backgroundColor = randomColorGenerator();
  });
  document.querySelectorAll(".gameColorOption")[
    randomNumber
  ].style.backgroundColor = correctColor;

  document.querySelector(".gameQtsColor").innerHTML = correctColor;
  document.querySelectorAll(".gameColorOption").forEach((btn) => {
    btn.addEventListener("click", (e) => {
      if (e.target.style.backgroundColor === correctColor) {
        document.querySelector(".gameMessage").innerHTML = "Correct!";
        document.querySelectorAll(".gameColorOption").forEach((btn) => {
          btn.style.backgroundColor = correctColor;
        });
      } else {
        document.querySelector(".gameMessage").innerHTML = "Wrong!";
        e.target.style.transform = "scale(1.2)";
        e.target.style.border = "4px solid red";
      }
    });
  });
}
@import url("https://fonts.googleapis.com/css2?family=Gochi+Hand&display=swap");
body {
  background-color: #456064;
}

.navbar {
  background-color: #2e4144;
  font-family: "Gochi Hand", cursive;
  font-size: 28px;
  border-bottom: 2px solid #456064;
  box-shadow: 0px 6px 16px rgba(0, 0, 0, .3);
}

.navbar-brand {
  font-size: 28px;
}

.nav-link:hover {
  text-decoration: underline;
}

.colorCodeSelection {
  display: flex;
  align-items: center;
  justify-content: center;
}

.colorCodeBtn:first-child {
  border-top-left-radius: 100px;
  border-bottom-left-radius: 100px;
}

.colorCodeBtn:last-child {
  border-top-right-radius: 100px;
  border-bottom-right-radius: 100px;
}

.colorCodeBtn {
  margin: 0;
  margin-top: 20px;
  outline: none;
  background-color: transparent;
  border: 1px solid white;
  font-family: "Gochi Hand", cursive;
  color: white;
  font-size: 24px;
}

.selectedColorCode {
  background-color: white;
  color: #456064;
}

.gameContainer {
  font-family: "Gochi Hand", cursive;
  color: white;
}

.gameQtsColor {
  font-size: 60px;
  line-height: 60px;
}

.gameColorsContainer {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}

.gameOptionsRow {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
}

.gameColorOption {
  background-color: chartreuse;
  height: 150px;
  width: 150px;
  margin: 25px;
  border-radius: 16px;
  cursor: pointer;
  transition: all 150ms ease-in-out;
}

.gameColorOption:hover {
  transform: scale(1.15);
  box-shadow: 4px 6px 24px hsla(188, 19%, 20%, 0.3);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Colors and Numbers</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" />
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" />
  <link rel="stylesheet" href="style.css" />
</head>

<body>
  <!-- Navbar -->
  <nav class="navbar navbar-expand-lg navbar-dark">
    <div class="container-fluid">
      <a class="navbar-brand ms-2 mt-2 me-5" href="/">
        <i class="bi bi-palette-fill"></i> &
        <i class="bi bi-dice-3-fill"></i>
      </a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="/">Game</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" aria-current="page" href="/generator">
                Generator
              </a>
          </li>
          <li class="nav-item">
            <a class="nav-link" aria-current="page" href="/converter">
                Converter
              </a>
          </li>
        </ul>
      </div>
    </div>
  </nav>
  <!--* Navbar End -->
  <!-- Game Body -->
  <div class="colorCodeSelection">
    <button class="colorCodeBtn selectedColorCode" game-mode="rgb">RGB</button>
    <button class="colorCodeBtn" game-mode="hex">HEX</button>
    <button class="colorCodeBtn" game-mode="hsl">HSL</button>
  </div>
  <div class="gameContainer container mt-5">
    <p class="h3 text-center mt-5">Which Color is this?</p>
    <p class="gameQtsColor text-center">rgb(20, 30, 40)</p>
    <p class="text-center h3 gameMessage">Select from below!</p>
    <div class="gameColorsContainer container-fluid">
      <div class="gameOptionsRow">
        <div class="gameColorOption"></div>
        <div class="gameColorOption"></div>
        <div class="gameColorOption"></div>
      </div>
      <div class="gameOptionsRow">
        <div class="gameColorOption"></div>
        <div class="gameColorOption"></div>
        <div class="gameColorOption"></div>
      </div>
    </div>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
<script src="script.js"></script>

</html>

【问题讨论】:

  • 那么,如果你 console.log selectedGameModegameRunner 之前显示正确的值? gameRunner如何处理选择的游戏模式?
  • @beto gameRunner 与选择的游戏模式无关。 selectedGameMode 仅适用于 randomColorGenerator() 函数
  • 你在哪里执行randomColorGenerator()?不应该在设置selectedGameMode之后,在游戏运行之前执行吗?
  • 你能在第一个 sn-p 代码周围添加更多上下文吗?那怎么叫?它在一个函数中吗?为什么要将点击事件添加到执行该代码的相同按钮?
  • @beto 当我必须决定颜色时,randomColorGenerator()gameRunner() 中被调用

标签: javascript


【解决方案1】:

我发现了一些问题

  1. 通过 element.style.backgroundColor 设置背景颜色会将您设置的值转换为 rgb/a,因此无论您使用 hex 还是 hsl,您最终都会使用 rgb(请参阅 here)。
    如果您想保留您使用的样式的方法,您可以使用 setAttribute/getAttribute 设置颜色并重新测试。
  2. 您构建 hsl 和十六进制颜色的方式看起来不正确(请参阅代码更改)
  3. correctColor 变量没有改变,这是因为添加到.gameColorOption div 的事件侦听器创建的闭包。我将此变量设为全局变量以避免该问题。
  4. randomNumber 代码可能会生成一个值 6,该值太大而无法选择 .gameColorOption,并会导致错误。使用Math.round(Math.random() * 5)
    let selectedGameMode = "rgb";
    let correctColor;
    gameRunner();
    document.querySelectorAll(".colorCodeBtn").forEach((btn) => {
      btn.addEventListener("click", () => {
        if (btn.classList.contains("selectedColorCode")) return;
        btn.parentElement
          .querySelector(".selectedColorCode")
          .classList.remove("selectedColorCode");
        btn.classList.add("selectedColorCode");
        selectedGameMode = btn.getAttribute("game-mode");
        gameRunner();
      });
    });
    
    function randomColorGenerator() {
      let red = Math.round(Math.random() * 255);
      let green = Math.round(Math.random() * 255);
      let blue = Math.round(Math.random() * 255);
      if (selectedGameMode == "rgb") {
        return `rgb(${red}, ${green}, ${blue})`;
      } else if (selectedGameMode == "hex") {
        let hexRed = red.toString(16).padStart(2, '0');
        let hexGreen = green.toString(16).padStart(2, '0');
        let hexBlue = blue.toString(16).padStart(2, '0');
        return `#${hexRed + hexGreen + hexBlue}`;
      } else if (selectedGameMode == "hsl") {
        let h = Math.round(Math.random() * 360);
        let s = Math.round(Math.random() * 100) + "%";
        let l = Math.round(Math.random() * 100) + "%";
        return `hsl(${h}deg ${s} ${l})`;
      }
    }
    
    function gameRunner() {
      correctColor = randomColorGenerator();
      let randomNumber = Math.round(Math.random() * 5);
      document.querySelectorAll(".gameColorOption").forEach((btn) => {
        btn.setAttribute('style', 'background-color: ' + randomColorGenerator());
      });
      document.querySelectorAll(".gameColorOption")[
        randomNumber
      ].setAttribute('style', 'background-color: ' + correctColor);
    
      document.querySelector(".gameQtsColor").innerHTML = correctColor;
      document.querySelectorAll(".gameColorOption").forEach((btn) => {
        btn.addEventListener("click", (e) => {
          if (e.target.getAttribute('style').substr(18) === correctColor) {
            document.querySelector(".gameMessage").innerHTML = "Correct!";
            document.querySelectorAll(".gameColorOption").forEach((btn) => {
              btn.style.backgroundColor = correctColor;
            });
          } else {
            document.querySelector(".gameMessage").innerHTML = "Wrong!";
            e.target.style.transform = "scale(1.2)";
            e.target.style.border = "4px solid red";
          }
        });
      });
    }
    @import url("https://fonts.googleapis.com/css2?family=Gochi+Hand&display=swap");
    body {
      background-color: #456064;
    }
    
    .navbar {
      background-color: #2e4144;
      font-family: "Gochi Hand", cursive;
      font-size: 28px;
      border-bottom: 2px solid #456064;
      box-shadow: 0px 6px 16px rgba(0, 0, 0, .3);
    }
    
    .navbar-brand {
      font-size: 28px;
    }
    
    .nav-link:hover {
      text-decoration: underline;
    }
    
    .colorCodeSelection {
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    .colorCodeBtn:first-child {
      border-top-left-radius: 100px;
      border-bottom-left-radius: 100px;
    }
    
    .colorCodeBtn:last-child {
      border-top-right-radius: 100px;
      border-bottom-right-radius: 100px;
    }
    
    .colorCodeBtn {
      margin: 0;
      margin-top: 20px;
      outline: none;
      background-color: transparent;
      border: 1px solid white;
      font-family: "Gochi Hand", cursive;
      /*color: white;*/
      font-size: 24px;
    }
    
    .selectedColorCode {
      background-color: white;
      color: #456064;
    }
    
    .gameContainer {
      font-family: "Gochi Hand", cursive;
      /*color: white;*/
    }
    
    .gameQtsColor {
      font-size: 60px;
      line-height: 60px;
    }
    
    .gameColorsContainer {
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;
    }
    
    .gameOptionsRow {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
    }
    
    .gameColorOption {
      background-color: chartreuse;
      height: 150px;
      width: 150px;
      margin: 25px;
      border-radius: 16px;
      cursor: pointer;
      transition: all 150ms ease-in-out;
    }
    
    .gameColorOption:hover {
      transform: scale(1.15);
      box-shadow: 4px 6px 24px hsla(188, 19%, 20%, 0.3);
    }
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>Colors and Numbers</title>
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" />
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" />
      <link rel="stylesheet" href="style.css" />
    </head>
    
    <body>
      <!-- Navbar -->
      <nav class="navbar navbar-expand-lg navbar-dark">
        <div class="container-fluid">
          <a class="navbar-brand ms-2 mt-2 me-5" href="/">
            <i class="bi bi-palette-fill"></i> &
            <i class="bi bi-dice-3-fill"></i>
          </a>
          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
              <span class="navbar-toggler-icon"></span>
            </button>
          <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
              <li class="nav-item">
                <a class="nav-link active" aria-current="page" href="/">Game</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" aria-current="page" href="/generator">
                    Generator
                  </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" aria-current="page" href="/converter">
                    Converter
                  </a>
              </li>
            </ul>
          </div>
        </div>
      </nav>
      <!--* Navbar End -->
      <!-- Game Body -->
      <div class="colorCodeSelection">
        <button class="colorCodeBtn selectedColorCode" game-mode="rgb">RGB</button>
        <button class="colorCodeBtn" game-mode="hex">HEX</button>
        <button class="colorCodeBtn" game-mode="hsl">HSL</button>
      </div>
      <div class="gameContainer container mt-5">
        <p class="h3 text-center mt-5">Which Color is this?</p>
        <p class="gameQtsColor text-center">rgb(20, 30, 40)</p>
        <p class="text-center h3 gameMessage">Select from below!</p>
        <div class="gameColorsContainer container-fluid">
          <div class="gameOptionsRow">
            <div class="gameColorOption"></div>
            <div class="gameColorOption"></div>
            <div class="gameColorOption"></div>
          </div>
          <div class="gameOptionsRow">
            <div class="gameColorOption"></div>
            <div class="gameColorOption"></div>
            <div class="gameColorOption"></div>
          </div>
        </div>
      </div>
    </body>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
    <script src="script.js"></script>
    
    </html>

【讨论】:

    【解决方案2】:

    您的代码中有错误:

    let randomNumber = Math.round(Math.random() * 6);
    

    这可以四舍五入为6,这意味着当它变成6时,该行:

    document.querySelectorAll(".gameColorOption")[randomNumber].setAttribute('style', 'background-color: ' + correctColor);
    

    undefined 元素为目标。请记住,数组和类似数组的结构从索引 0 开始,因此您只需要 0 到 5 之间的数字来处理 6 个颜色的图块。

    这就是导致您的游戏模式进入不良状态的原因。如果您在按钮上单击一堆,最终您会在控制台中看到错误:

    js:220 Uncaught TypeError: Cannot read properties of undefined (reading 'style')
        at gameRunner (js:220)
        at HTMLButtonElement.<anonymous> (js:184)
    

    为确保您只获得 0 到 5 之间的数字,您应该将其更改为:

    let randomNumber = Math.floor(Math.random() * 5);
    

    【讨论】:

    • 仍然没有解决为什么更改游戏模式后游戏选项中的颜色没有变化。但是,我仍然会确保修复这个问题。谢谢
    猜你喜欢
    • 2021-11-09
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    相关资源
    最近更新 更多