HTML5 canvas 图像未使用 drawImage() 加载
HTML5 canvas images are not loading using drawImage()
我正在关注 freeCodeCamp 的飞鸟游戏教程
https://www.youtube.com/watch?v=pufKO5EG8nc
但我正在使用 class 来了解更多信息。
问题是,图像无法加载,而在视频中却可以正常加载。
我四处搜索并了解了 onload 事件,并在那里实现了它,但仍然没有任何反应,控制台中也没有错误消息。
即使没有 onload 事件,为什么视频的图像加载了,而我的却没有? >:(
我的HTML代码:
<canvas id="canvas" width="512" height="512">
</canvas>
我的JS代码:
const canvas = document.querySelector("#canvas");
class Game {
constructor(c) {
this.c = c; //canvas
this.ctx = c.getContext("2d"); // context
this.sprites = 5;
this.loadedSprites = 0;
this.player = new Image(); // define images
this.bg = new Image();
this.fg = new Image();
this.north = new Image();
this.south = new Image();
this.pX = 10; // player starting location
this.pY = 150;
// set sprite locations and load.
this.player.src = "images/crab.png";
this.player.onload = this.draw;
this.bg.src = "images/bg.png";
this.bg.onload = this.draw;
this.fg.src = "images/fg.png";
this.fg.onload = this.draw;
this.north.src = "images/obstacle.png";
this.gap = 80;
this.constant = this.north.height + this.gap;
this.north.onload = this.draw;
this.south.src = "images/obstacle.png";
this.south.onload = this.draw;
}
//draw images
draw() {
this.loadedSprites += 1;
if (this.loadedSprites >= this.sprites) {
this.ctx.drawImage(this.bg, 0, 0);
this.ctx.drawImage(this.north, 100, 0);
this.ctx.drawImage(this.south, 0, 0 + this.constant);
this.ctx.drawImage(this.fg, 0, this.c.height - this.fg.height);
this.ctx.drawImage(this.player, this.pX, this.pY);
}
}
}
let game = new Game(canvas);
您的问题与 scope 有关 - 它指的是变量、对象和函数的可访问性 - 以及 this 关键字取决于实际范围。
为了更好地理解让我们看下面的例子:
class Game {
constructor() {
console.log("Game constructor:", this);
this.player = new Image();
this.player.onload = this.draw;
this.player.src = "https://picsum.photos/200/300";
}
draw() {
console.log("draw:", this);
}
}
let game = new Game();
如果单击 'Run code snippet',您应该会在控制台中看到以下输出:
Game constructor: {}
draw: <img src="https://picsum.photos/200/300"></img>
如您所见,draw()
中对 this 的调用不再指向同一事物。在第一种情况下,它是 Game 的对象实例(由大括号提示),在第二种情况下,它是 HTMLImageElement 的实例。
所以你的代码失败了,因为:
this.loadedSprites += 1;
if (this.loadedSprites >= this.sprites) {
不要引用游戏 class 的私有变量 loadedSprites
和 sprites
- 事实上它根本没有引用任何东西,因为它在因此绘图函数 loadedSprites
永远不会增加。
一种解决方法是使用新的 属性 将游戏 class 的上下文传递给每个图像实例,例如.reference
.
this.player = new Image();
this.player.reference = this;
this.player.onload = this.draw;
并在 draw() 中使用它,例如:
draw() {
this.reference.loadedSprites += 1;
}
这是一个基于您的代码的完整示例:
const canvas = document.querySelector("#canvas");
class Game {
constructor(c) {
this.c = c; //canvas
this.ctx = c.getContext("2d"); // context
this.sprites = 5;
this.loadedSprites = 0;
this.player = new Image(); // define images
this.player.reference = this;
this.bg = new Image();
this.bg.reference = this;
this.fg = new Image();
this.fg.reference = this;
this.north = new Image();
this.north.reference = this;
this.south = new Image();
this.south.reference = this;
this.pX = 10; // player starting location
this.pY = 150;
// set sprite locations and load.
this.player.onload = this.draw;
this.player.src = "https://picsum.photos/id/237/20/20";
this.bg.onload = this.draw;
this.bg.src = "https://picsum.photos/id/22/20/20";
this.fg.onload = this.draw;
this.fg.src = "https://picsum.photos/id/30/20/20";
this.gap = 80;
this.constant = this.north.height + this.gap;
this.north.onload = this.draw;
this.north.src = "https://picsum.photos/id/37/20/20";
this.south.onload = this.draw;
this.south.src = "https://picsum.photos/id/137/20/20";
}
//draw images
draw() {
let ref = this.reference;
ref.loadedSprites += 1;
if (ref.loadedSprites >= ref.sprites) {
ref.ctx.drawImage(ref.bg, 0, 0);
ref.ctx.drawImage(ref.north, 100, 0);
ref.ctx.drawImage(ref.south, 0, 0 + ref.constant);
ref.ctx.drawImage(ref.fg, 0, ref.c.height - ref.fg.height);
ref.ctx.drawImage(ref.player, ref.pX, ref.pY);
}
}
}
let game = new Game(canvas);
<canvas id="canvas" width="512" height="512">
</canvas>
我正在关注 freeCodeCamp 的飞鸟游戏教程 https://www.youtube.com/watch?v=pufKO5EG8nc
但我正在使用 class 来了解更多信息。
问题是,图像无法加载,而在视频中却可以正常加载。
我四处搜索并了解了 onload 事件,并在那里实现了它,但仍然没有任何反应,控制台中也没有错误消息。
即使没有 onload 事件,为什么视频的图像加载了,而我的却没有? >:(
我的HTML代码:
<canvas id="canvas" width="512" height="512">
</canvas>
我的JS代码:
const canvas = document.querySelector("#canvas");
class Game {
constructor(c) {
this.c = c; //canvas
this.ctx = c.getContext("2d"); // context
this.sprites = 5;
this.loadedSprites = 0;
this.player = new Image(); // define images
this.bg = new Image();
this.fg = new Image();
this.north = new Image();
this.south = new Image();
this.pX = 10; // player starting location
this.pY = 150;
// set sprite locations and load.
this.player.src = "images/crab.png";
this.player.onload = this.draw;
this.bg.src = "images/bg.png";
this.bg.onload = this.draw;
this.fg.src = "images/fg.png";
this.fg.onload = this.draw;
this.north.src = "images/obstacle.png";
this.gap = 80;
this.constant = this.north.height + this.gap;
this.north.onload = this.draw;
this.south.src = "images/obstacle.png";
this.south.onload = this.draw;
}
//draw images
draw() {
this.loadedSprites += 1;
if (this.loadedSprites >= this.sprites) {
this.ctx.drawImage(this.bg, 0, 0);
this.ctx.drawImage(this.north, 100, 0);
this.ctx.drawImage(this.south, 0, 0 + this.constant);
this.ctx.drawImage(this.fg, 0, this.c.height - this.fg.height);
this.ctx.drawImage(this.player, this.pX, this.pY);
}
}
}
let game = new Game(canvas);
您的问题与 scope 有关 - 它指的是变量、对象和函数的可访问性 - 以及 this 关键字取决于实际范围。
为了更好地理解让我们看下面的例子:
class Game {
constructor() {
console.log("Game constructor:", this);
this.player = new Image();
this.player.onload = this.draw;
this.player.src = "https://picsum.photos/200/300";
}
draw() {
console.log("draw:", this);
}
}
let game = new Game();
如果单击 'Run code snippet',您应该会在控制台中看到以下输出:
Game constructor: {}
draw: <img src="https://picsum.photos/200/300"></img>
如您所见,draw()
中对 this 的调用不再指向同一事物。在第一种情况下,它是 Game 的对象实例(由大括号提示),在第二种情况下,它是 HTMLImageElement 的实例。
所以你的代码失败了,因为:
this.loadedSprites += 1;
if (this.loadedSprites >= this.sprites) {
不要引用游戏 class 的私有变量 loadedSprites
和 sprites
- 事实上它根本没有引用任何东西,因为它在因此绘图函数 loadedSprites
永远不会增加。
一种解决方法是使用新的 属性 将游戏 class 的上下文传递给每个图像实例,例如.reference
.
this.player = new Image();
this.player.reference = this;
this.player.onload = this.draw;
并在 draw() 中使用它,例如:
draw() {
this.reference.loadedSprites += 1;
}
这是一个基于您的代码的完整示例:
const canvas = document.querySelector("#canvas");
class Game {
constructor(c) {
this.c = c; //canvas
this.ctx = c.getContext("2d"); // context
this.sprites = 5;
this.loadedSprites = 0;
this.player = new Image(); // define images
this.player.reference = this;
this.bg = new Image();
this.bg.reference = this;
this.fg = new Image();
this.fg.reference = this;
this.north = new Image();
this.north.reference = this;
this.south = new Image();
this.south.reference = this;
this.pX = 10; // player starting location
this.pY = 150;
// set sprite locations and load.
this.player.onload = this.draw;
this.player.src = "https://picsum.photos/id/237/20/20";
this.bg.onload = this.draw;
this.bg.src = "https://picsum.photos/id/22/20/20";
this.fg.onload = this.draw;
this.fg.src = "https://picsum.photos/id/30/20/20";
this.gap = 80;
this.constant = this.north.height + this.gap;
this.north.onload = this.draw;
this.north.src = "https://picsum.photos/id/37/20/20";
this.south.onload = this.draw;
this.south.src = "https://picsum.photos/id/137/20/20";
}
//draw images
draw() {
let ref = this.reference;
ref.loadedSprites += 1;
if (ref.loadedSprites >= ref.sprites) {
ref.ctx.drawImage(ref.bg, 0, 0);
ref.ctx.drawImage(ref.north, 100, 0);
ref.ctx.drawImage(ref.south, 0, 0 + ref.constant);
ref.ctx.drawImage(ref.fg, 0, ref.c.height - ref.fg.height);
ref.ctx.drawImage(ref.player, ref.pX, ref.pY);
}
}
}
let game = new Game(canvas);
<canvas id="canvas" width="512" height="512">
</canvas>