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

时间:2015-10-22 13:15:25

标签: javascript css ecmascript-6 babeljs

我正在尝试基于类的代码。我为画布创建了一个类,然后将一个组件传递给它,然后再渲染它。问题是当浏览器请求动画帧时,上下文丢失,并且变得不确定。我正在寻找解释为什么会出现这种情况的原因。

我并不关心最佳实践,只是弄清楚为什么背景会丢失。

我在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
}));

1 个答案:

答案 0 :(得分:7)

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

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