首页 > 解决方案 > 删除放置在画布上的最后一个图形,但不断获取 getContext 不是函数

问题描述

我是 JavaScript 新手,这是我第一次使用 HTML5 画布,所以请原谅这是一个简单的修复。

我使用画布创建了一个井字游戏,每次单击画布方块时都会放置一个 png 或 SVG。我现在正在尝试创建一个撤消按钮,可以删除最后一次移动。我正在尝试使用 clearRect() 函数删除图形,虽然图形确实消失了,但控制台显示错误“Uncaught TypeError: box.getContext is not a function”......这很奇怪,因为我没有当我使用“box.getContext”将图形放在首位时不会出现此错误。

不仅如此,当我尝试再次单击清除的画布方块时,它不允许放置图形......关于为什么会发生这种情况的任何想法?

(顺便说一句,我对 X 使用 png 对 O 使用 SVG 只是为了练习每种类型的图形)

这是我的 JS:

window.onload = function() {
  var num;
  var box;
  var ctx;
  var turn = 1;
  var filled;
  var symbol;
  var winner;
  var gameOver = false;

  filled = [false, false, false, false, false, false, false, false, false];
  symbol = ["", "", "", "", "", "", "", "", ""];
  winner = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
  ];


  //canvas click + retrieving the box's number
  document.getElementById("tic").addEventListener("click", function(e) {
    boxClick(e.target.id);
  });

  function boxClick(numId) {
    box = document.getElementById(numId);
    ctx = box.getContext("2d"); /*here is where I'm getting the error*/

    switch (numId) {
      case "square1":
        num = 1;
        break;
      case "square2":
        num = 2;
        break;
      case "square3":
        num = 3;
        break;
      case "square4":
        num = 4;
        break;
      case "square5":
        num = 5;
        break;
      case "square6":
        num = 6;
        break;
      case "square7":
        num = 7;
        break;
      case "square8":
        num = 8;
        break;
      case "square9":
        num = 9;
        break;
    }

    //drawing the shapes on the canvases (switch to 0 indexing later)
    if (filled[num - 1] == false) {
      if (gameOver == false) {
        if (turn % 2 != 0) {
          var sean_image = new Image();
          sean_image.src = "graphics/sean.png";
          sean_image.onload = function() {
            ctx.drawImage(sean_image, -43, -26);
          };
          symbol[num - 1] = "X";
        } else {
          //if number is even (O player)
          var square_svg = new Image();
          square_svg.src = "graphics/square.svg";
          square_svg.onload = function() {
            ctx.drawImage(square_svg, 8.5, 8.5);
          };
          symbol[num - 1] = "O";
        }


/* ***this is where I'm trying to implement the undo function */
        //undo the last move made
        document.getElementById("undo").onclick = function() {
          ctx.clearRect(0, 0, box.width, box.height);
          filled[num - 1] == false;
          symbol[num - 1] = "";
        };
      } 
    } 
  }
};

这是我的 HTML:

<!DOCTYPE html>
<html>
  <head>
    <title>Tic Tac Toe</title>
    <meta charset="utf-8" />

    <link rel="stylesheet" type="text/css" href="ticTacToe.css" />
  </head>
  <body>
    <header>
      <h1 id="head">Tic Tac Toe Game</h1>
    </header>
    <h1 id="result"></h1>

    <section id="game">
      <div id="tic">
        <canvas id="square1" width="100" height="100"></canvas>
        <canvas id="square2" width="100" height="100"></canvas>
        <canvas id="square3" width="100" height="100"></canvas><br />

        <canvas id="square4" width="100" height="100"></canvas>
        <canvas id="square5" width="100" height="100"></canvas>
        <canvas id="square6" width="100" height="100"></canvas><br />

        <canvas id="square7" width="100" height="100"></canvas>
        <canvas id="square8" width="100" height="100"></canvas>
        <canvas id="square9" width="100" height="100"></canvas>

        <button id="undo">Undo Move</button>
      </div>
    </section>

    <script type="text/javascript" src="ticTacToe.js"></script>
  </body>
</html>

标签: javascripthtmlcanvas

解决方案


这是因为您将单击事件侦听器附加到 id 的 div 上tic。因此,如果您单击该 div 内的任何内容tic,该事件侦听器将触发。因为撤消按钮在ticdiv 内部,所以当它被单击时,该事件侦听器将触发并e.target代表被单击的撤消按钮。由于该撤消按钮不是画布元素,因此该getContext方法将无法在其上正常工作,您将收到该错误。

因此,您应该将该按钮元素移到 div 之外,并使用id=tic. 我会把它放在tic div的正下方。


推荐阅读