Canvas 调用 requestAnimationFrame 时无法找到上下文 - ES6

Canvas unable to find context when requestAnimationFrame is called - ES6

我正在试验基于 class 的代码。我为 canvas 创建了一个 class 并将一个组件传递给它,然后将其渲染。问题是,当浏览器请求动画帧时,上下文丢失,并变得未定义。我正在寻找为什么会这样的解释。

我不关心最佳实践,只是想弄清楚上下文丢失的原因。

我已将 link 附加到 codepen 上的示例。

http://codepen.io/BrianDGLS/pen/BoJorM?editors=001

这里是JS代码:

class Canvas {
  constructor() {
    this.canvas = document.getElementById('canvas');
    this.context = this.canvas.getContext('2d');
    this.width = this.canvas.width = window.innerHeight;
    this.height = this.canvas.height = window.innerWidth;
    this.components = [];
  }

  draw() {
    this.context.clearRect(0, 0, this.width, this.height);
    this.context.globalCompositeOperation = 'hard-light';

    this.components.map(_ => _.render());

    window.requestAnimationFrame(this.draw);
  }

  listeners() {
    window.addEventListener('resize', () => {
      this.width = this.canvas.width = window.innerHeight;
      this.height = this.canvas.height = window.innerWidth;
    }, false);
  }

  init() {
    this.listeners();
    this.draw();
  }
}

class Utils {
  randomNum(max, min) {
    return Math.floor(max * Math.random()) + min;
  }

  color(opacity) {
    return `hsla(${this.randomNum(360, 1)}, 70%, 60%, ${opacity})`;
  }
}

const utils = new Utils();
const _canvas = new Canvas();

class Stars {
  constructor(_) {
    this.total = _.total;
    this.spawn = [];
    this.z = 300;
    this.canvas = _.canvas;
    this.xw = this.canvas.width * this.z;
    this.xh = this.canvas.height * this.z;
  }

  create() {
    while (this.spawn.length < this.total) {
      this.spawn.push({
        pos: [this.xw * Math.random() - this.canvas.width / 2 * this.z, this.xh * Math.random() - this.canvas.height / 2 * this.z, this.z],
        vel: [0, 0, -2],
        r: utils.randomNum(500, 100),
        color: utils.color(1)
      });
    }
  }

  draw() {
    for (let i = 0; i < this.spawn.length; ++i) {
      let t = this.spawn[i];
      let x = t.pos[0] / t.pos[2];
      let y = t.pos[1] / t.pos[2];
      if (x < -this.canvas.width / 2 || x > this.canvas.width / 2 || y < -this.canvas.height / 2 || y > this.canvas.height / 2 || t.pos[2] < 0) {
        this.spawn.splice(i, 1);
        --i;
        continue;
      }
      this.canvas.context.beginPath();
      this.canvas.context.fillStyle = t.color;
      this.canvas.context.arc(x, y, t.r / t.pos[2], 0, Math.PI * 2, false);
      t.pos[0] += t.vel[0];
      t.pos[1] += t.vel[1];
      t.pos[2] += t.vel[2];
      this.canvas.context.fill();
    }
  }

  render() {
    this.create();
    this.canvas.context.save();
    this.canvas.context.translate(this.canvas.width / 2, this.canvas.height / 2);
    this.draw();
    this.canvas.context.restore();
  }
}

_canvas.components.push(new Stars({
  canvas: _canvas,
  total: 200
}));

当您通过 window.requestAnimationFrame(this.draw) 调用 draw() 时,draw() 中的范围绑定到 window 而不是 Canvas。尝试像这样显式绑定范围:

window.requestAnimationFrame(this.draw.bind(this));