我试图创建一个以画布为对象的类,以尝试了解有关类的更多信息。我编写了以下代码,但除了空白屏幕外,什么也没有。
class Canvas
{
constructor(canvasId = 'canvas', dimension = '2d', canvasWidth = document.body.clientWidth,canvasHeight = window.innerHeight,canvasDisplay = 'block',canvasOverflow = 'hidden')
{
// Initialize Canvas and Context variables
this.can = document.getElementById(canvasId);
this.ctx = this.can.getContext(dimension);
// Set canvas properties
this.can.width = canvasWidth;
this.can.height = canvasHeight;
this.can.style.display = canvasDisplay;
this.can.style.overflow = canvasOverflow;
this.count = 0;
}
display(ctx)
{
var ctx = ctx;
var scrollSS = new Image();
scrollSS.src = "../../../Assets/Media/Images/Scroll/ScrollSpriteSheet.png";
ctx.drawImage(scrollSS,0,0,102,345,10,0,canvas.width / 10,canvas.height);
}
animate(ctx)
{
var ctx = ctx;
console.log(this.count);
this.count++;
this.display(ctx)
requestAnimationFrame(this.animate(ctx));
}
}
var canvas = new Canvas();
console.log(canvas.ctx);
canvas.animate(canvas.ctx);
我做错什么了吗?
答案 0 :(得分:2)
您的问题是您正在animate()
方法中一次又一次地调用requestAnimationFrame()
。相反,当requestAnimationFrame()决定这样做时,您需要让JS为您调用函数animate
。
这意味着您需要将animate
函数传递给requestAnimationFrame
,而不是实际的函数 call (因为调用该函数时,您实际上是在通过它返回值):
requestAnimationFrame(this.animate.bind(this));
由于JS将处理animate
方法的调用,因此this
内部的animate()
(当被调用时)将不是您的Canvas
对象,而是{ {1}}。要使window
引用您的this
对象,您需要Canvas
使用.bind(this)
函数。以上等同于使用箭头功能:
animate
您的另一个问题是您试图在图像加载之前显示它。您首先需要加载图像,然后显示它。如果您的图像将保持不变,建议您在绘制之前先加载它,而不是每次要重绘时都加载它(请参见第二代码段)。
此外,requestAnimationFrame(() => this.animate());
是画布实例的一部分。每个画布对象将具有在构造函数中定义的ctx
属性。因此,无需将其作为.ctx
或animate
的参数传递,因为您可以使用display
来访问它。
请参见下面的示例(请注意,该图像是临时图像):
this.ctx
class Canvas {
constructor(canvasId = 'canvas', dimension = '2d', canvasWidth = document.body.clientWidth, canvasHeight = window.innerHeight, canvasDisplay = 'block', canvasOverflow = 'hidden') {
// Initialize Canvas and Context variables
this.can = document.getElementById(canvasId);
this.ctx = this.can.getContext(dimension);
// Set canvas properties
this.can.width = canvasWidth;
this.can.height = canvasHeight;
this.can.style.display = canvasDisplay;
this.can.style.overflow = canvasOverflow;
this.count = 0;
}
display() {
var ctx = this.ctx;
var scrollSS = new Image();
scrollSS.src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRha_-J-uQR_8pUrUQOiPYZ_JXRoqfoqDt8BO8icSfkworyz9woQQ&s";
scrollSS.addEventListener('load', e => {
ctx.drawImage(scrollSS, 0, 0, 102, 345, 10, 0, this.can.width / 10, this.can.height);
});
}
animate() {
this.count++;
this.display();
requestAnimationFrame(this.animate.bind(this));
}
}
var canvas = new Canvas();
canvas.animate();
这是使用Promises的一种方法,如果您只需要加载一个图像,则可能要采用这种方法:
<canvas id="canvas" style="border: 1px solid black"></canvas>
class Canvas {
constructor(canvasId = 'canvas', dimension = '2d', canvasWidth = document.body.clientWidth, canvasHeight = window.innerHeight, canvasDisplay = 'block', canvasOverflow = 'hidden') {
// Initialize Canvas and Context variables
this.can = document.getElementById(canvasId);
this.ctx = this.can.getContext(dimension);
// Set canvas properties
this.can.width = canvasWidth;
this.can.height = canvasHeight;
this.can.style.display = canvasDisplay;
this.can.style.overflow = canvasOverflow;
this.count = 0;
}
loadImage(url) {
var img = new Image();
img.src = url;
return new Promise((resolve) => {
img.addEventListener('load', function(e) {
resolve(this);
});
});
}
display(img) {
var ctx = this.ctx;
ctx.drawImage(img, 0, 0, 102, 345, 10, 0, this.can.width / 10, this.can.height);
}
animate(img) {
this.count++;
this.display(img);
requestAnimationFrame(this.animate.bind(this, img));
}
}
var canvas = new Canvas();
var img_url = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRha_-J-uQR_8pUrUQOiPYZ_JXRoqfoqDt8BO8icSfkworyz9woQQ&s";
canvas
.loadImage(img_url)
.then(function(image) {
canvas.animate(image);
});