Typescript/JavaScript:为什么我的 canvas 和 canvas 上下文未定义,即使我已经初始化了它们?

Typescript/JavaScript: Why is my canvas and canvas context undefined, even though I initialized them?

我正在 Angular 的 Typescript 中玩弄网格。我将 canvas 和上下文定义为全局变量,并在 ngOnInit() 中初始化它们。之后,我调用了一个使用 canvas 和上下文的函数。在控制台中,我收到以下错误:ERROR TypeError: Cannot read property 'ctxGrid' of undefined at resetGrid (grid-draw.component.ts:69)

我不知道我做错了什么,因为我已经初始化了两个变量。这可能是我不知道的事情。谢谢你。这是我的代码:

import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';

@Component({
  selector: 'app-grid-draw',
  templateUrl: './grid-draw.component.html',
  styleUrls: ['./grid-draw.component.css']
})
export class GridDrawComponent implements OnInit {

  constructor() { }

  @ViewChild('canvas', { static: true })



  shapes;
  canvas;
  ctxGrid;
  ngOnInit(): void {
    const animDelay = 5;
    const startNodeColor = "#FF3600";
    const endNodeColor = "#00AB5C";

    //initialize array an grid
    this.shapes = new Array(100);
    for (let i = 0; i < this.shapes.length; i++) { this.shapes[i] = new Array(100) };
    this.canvas = <HTMLCanvasElement>document.getElementById('myCanvas');
    this.ctxGrid = this.canvas.getContext('2d');
    resetGrid();

    //walls
    this.canvas.addEventListener('mousemove', function (e) {
      const rect = this.canvas.getBoundingClientRect();

      let cx = e.clientX - rect.left;
      let cy = e.clientY - rect.top;
      //draw_erase_walls(e, cx, cy);
    })

    //single click for start and end nodes
    this.canvas.addEventListener('mousedown', function (e) {
      const rect = this.canvas.getBoundingClientRect();
      let cx = e.clientX - rect.left;
      let cy = e.clientY - rect.top;
      //changeStart(cx, cy);
      //changeEnd(cx, cy);
    })

    function resetGrid() {
      this.ctxGrid.lineWidth = 0.05;
      //grid with rectangles
      for (let i = 0; i < this.shapes.length; i++) {
        for (let j = 0; j < this.shapes[i].length; j++) {
          //variables
          let x = i * 20;
          let y = j * 20;
          let l = 20, w = 20;
          let type = ""

          //a* algorithm info
          let F = 0;
          let G = 0;
          let H = 0;
          if (i == 4 && j == 4) {    
            this.ctxGrid.fillStyle = startNodeColor;
            type = "Start"
            //draw it
            this.ctxGrid.strokeRect(x, y, l, w);
            this.ctxGrid.fillRect(x, y, l, w);
          }

          else if (i == (this.canvas.width / 20 - 5) && j == (this.canvas.height / 20 - 5)) {
            this.ctxGrid.fillStyle = endNodeColor;

            type = "End"
            //draw it
            this.ctxGrid.strokeRect(x, y, l, w);
            this.ctxGrid.fillRect(x, y, l, w);
          }

          else {
            //push the default square info
            this.ctxGrid.fillStyle = "#000000"
            //draw it
            this.ctxGrid.strokeRect(x, y, l, w);
          }
          this.shapes[i][j] = { x, y, l, w, i, j, type, F, G, H };  //x and y are grid coordinates, and i j is the index in array the square object is in
        }
      }
      //a_star_search();
    }
  }
}

是的,我的朋友,这也是我决定在这里的原因,让我试着为你解决这些问题..

import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';

@Component({
    selector: 'app-grid-draw',
    templateUrl: './grid-draw.component.html',
    styleUrls: ['./grid-draw.component.css']
})
export class GridDrawComponent implements OnInit {

    constructor() { }

    @ViewChild('canvas', { static: true })



    shapes;
    canvas;
    ctxGrid;
    ngOnInit(): void {
        const animDelay = 5;
        const startNodeColor = "#FF3600";
        const endNodeColor = "#00AB5C";

        //initialize array an grid
        this.shapes = new Array(100);
        for (let i = 0; i < this.shapes.length; i++) { this.shapes[i] = new Array(100) };
        this.canvas = <HTMLCanvasElement>document.getElementById('myCanvas');
        this.ctxGrid = this.canvas.getContext('2d');
        resetGrid();
        //walls
        this.canvas.addEventListener('mousemove', (e) => {
            const rect = this.canvas.getBoundingClientRect();

            let cx = e.clientX - rect.left;
            let cy = e.clientY - rect.top;
            //draw_erase_walls(e, cx, cy);
        })

        //single click for start and end nodes
        this.canvas.addEventListener('mousedown', (e) => {
            const rect = this.canvas.getBoundingClientRect();
            let cx = e.clientX - rect.left;
            let cy = e.clientY - rect.top;
            //changeStart(cx, cy);
            //changeEnd(cx, cy);
        })

    }

    resetGrid(): void {
        this.ctxGrid.lineWidth = 0.05;
        //grid with rectangles
        for (let i = 0; i < this.shapes.length; i++) {
            for (let j = 0; j < this.shapes[i].length; j++) {
                //variables
                let x = i * 20;
                let y = j * 20;
                let l = 20, w = 20;
                let type = ""

                //a* algorithm info
                let F = 0;
                let G = 0;
                let H = 0;
                if (i == 4 && j == 4) {
                    this.ctxGrid.fillStyle = startNodeColor;
                    type = "Start"
                    //draw it
                    this.ctxGrid.strokeRect(x, y, l, w);
                    this.ctxGrid.fillRect(x, y, l, w);
                }

                else if (i == (this.canvas.width / 20 - 5) && j == (this.canvas.height / 20 - 5)) {
                    this.ctxGrid.fillStyle = endNodeColor;

                    type = "End"
                    //draw it
                    this.ctxGrid.strokeRect(x, y, l, w);
                    this.ctxGrid.fillRect(x, y, l, w);
                }

                else {
                    //push the default square info
                    this.ctxGrid.fillStyle = "#000000"
                    //draw it
                    this.ctxGrid.strokeRect(x, y, l, w);
                }
                this.shapes[i][j] = { x, y, l, w, i, j, type, F, G, H };  //x and y are grid coordinates, and i j is the index in array the square object is in
            }
        }
        //a_star_search();
    }
}

希望它能这样工作。因为箭头函数没有上下文,它在移动或向下函数中使用你的组件上下文=)(至少它应该:)