Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
168 views
in Technique[技术] by (71.8m points)

javascript - 您如何将画布用作课程?(How do you use canvas as a class?)

I am trying to create a class which has a canvas as an object in an attempt learn more about classes.

(我试图创建一个以画布为对象的类,以尝试了解有关类的更多信息。)

I wrote the following code but it gives nothing but a blank screen.

(我编写了以下代码,但除了空白之外,它什么也没有。)


    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);

Am I doing something wrong?

(难道我做错了什么?)

  ask by WOLF CRECENT translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your issue is that you are calling animate() again and again within your requestAnimationFrame() method.

(您的问题是您在requestAnimationFrame()方法中一次又一次调用animate() 。)

You instead need to let JS call the function animate for you when requestAnimationFrame() decides to do so.

(相反,当requestAnimationFrame()决定这样做时,您需要让JS为您调用animate函数。)

This means you need to pass the animate function into requestAnimationFrame , not the actual function call (because when you call the function, you're really passing through its return value):

(这意味着您需要将animate函数传递给requestAnimationFrame ,而不是实际的函数调用 (因为调用该函数时,您实际上是在传递其返回值):)

requestAnimationFrame(this.animate.bind(this));

Since JS will handle the calling of the animate method, the this inside of animate() (when invoked) will not be your Canvas object, but rather the window .

(由于JS将处理animate方法的调用,因此animate animate()内部的this (在调用时)将不是Canvas对象,而是window 。)

To make this refer to your Canvas object you'll need to .bind(this) to your animate function.

(为了使this是指你的Canvas对象,你就需要.bind(this)你的animate功能。)

The above is equivalent to using an arrow function:

(以上等效于使用箭头功能:)

requestAnimationFrame(() => this.animate());

Your other issue is that you're trying to display the image before it has loaded.

(另一个问题是您试图在图像加载之前显示它。)

You firstly need to load the image and then display it.

(您首先需要加载图像,然后显示它。)

If your image is going to stay the same, I recommend you load it before you draw, rather than loading it every time you want to redraw (see second code snippet).

(如果您的图像将保持不变,建议您在绘制之前先加载它,而不是每次要重绘时都加载它(请参见第二代码段)。)

Also, ctx is part of your canvas instance.

(另外, ctx是画布实例的一部分。)

Each canvas object will have a .ctx property as it is defined in the constructor.

(每个画布对象将具有在构造函数中定义的.ctx属性。)

So, there is no need to pass it through as an argument to animate or display , as you can access it by using this.ctx .

(因此,无需传递它作为参数进行animatedisplay ,因为您可以使用this.ctx进行访问。)

See example below (note the image is a temporary image):

(请参见下面的示例(请注意该图像是临时图像):)

 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(); 
 <canvas id="canvas" style="border: 1px solid black"></canvas> 

Here is an approach using Promises that you might want to take if you only need to load the one image:

(如果只需要加载一个图像,则可以使用以下方法使用Promises :)

 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); }); 
 <canvas id="canvas" style="border: 1px solid black"></canvas> 


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...