Matt Ward
Matt Ward

Reputation: 1235

HTML5 Canvas - Draw image in update loop

I have a html5 canvas that I'm drawing circles with. These circles need images in the center of them, but also need to update. With the help of this SO question I have come up with this code to draw everything:

 var Circle1 = new Circle((c.width / 8) + (c.width / 2), 200, eighthWidth / 2.5, Color1, "1");    
 var Circle2 = new Circle(c.width - eighthWidth, 200, eighthWidth / 2.5, Color2, "2");

 function Circle(x, y, radius, color, name) {
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.color = color;
    this.name = name;

    this.draw = function () {
        var MiddleImage = new Image();
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
        ctx.fillStyle = this.color;
        ctx.fill();
        ctx.closePath();
        ctx.drawImage(MiddleImage, this.x - MiddleImage.width / 2, this.y - MiddleImage.height / 2);
        MiddleImage.src = "/Images/" + this.name + ".png";
    }

    this.update = function () {
        this.x += 1;
        this.draw();
    }

    this.update();
}

This isn't drawing the image like I hope it would, but if I take it out this method like below, it does work?

function drawCircle() {
    var MiddleImage = new Image();
    MiddleImage.onload = function () {
        var X = c.width - eighthWidth;
        var Y = 200;
        ctx.beginPath();
        ctx.arc(X, Y, eighthWidth / 2.5, 0, 2 * Math.PI);
        ctx.clip;
        ctx.fillStyle = Color1;
        ctx.fill();
        ctx.closePath();
        ctx.drawImage(MiddleImage, X - MiddleImage.width / 2, Y - MiddleImage.height / 2);
    };
    BankImage.src = "/Images/1.png";

    requestAnimationFrame(drawCircle);
}

I have also tried using the Image.onLoad method, as I have copied the working method into the new loop. The console is showing no errors.

You can see a JSFiddle here

Upvotes: 1

Views: 1282

Answers (1)

gugateider
gugateider

Reputation: 2039

The problem you're having is that you're loading the image within the draw function at every frame and not waiting for it to be loaded.

I've tweaked your code slightly so it will load and attach the image to your circle as you wish.

var c = document.getElementById('canvas');
c.width = window.innerWidth;
c.height = 400;
var ctx = c.getContext("2d");

var eighthWidth = c.width / 8;

var Color1 = "#9c9c9b";
var Color2 = "#9c9c9b";

var Circle1 = new Circle((c.width / 8) + (c.width / 2), 200, eighthWidth / 2.5, Color1, "1");
var Circle2 = new Circle(c.width - eighthWidth, 200, eighthWidth / 2.5, Color2, "2");

function Circle(x, y, radius, color, name) {
  this.x = x;
  this.y = y;
  this.radius = radius;
  this.color = color;
  this.name = name;
  this.image = new Image();
  this.image.src = "https://www.gstatic.com/webp/gallery3/1.png";
  var _this = this;
  
  this.image_loaded = false;
  this.image.addEventListener('load', function() {
  _this.image_loaded = true;
  } );

  this.draw = function() {
    
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.closePath();
    ctx.save();
    ctx.clip();
    
    ctx.drawImage(this.image, this.x - this.image.width / 2, this.y - this.image.height / 2);
    ctx.restore();
    
  }
  

  this.update = function() {
    //if(!this.image_loaded) return; 
    this.x += 1;
    this.draw();
  }
}

function animate() {
  ctx.clearRect(0, 0, window.innerWidth, 400);
  Circle1.update();
  Circle2.update();
  requestAnimationFrame(animate);
}
animate();
<canvas id="canvas" style="width:100%;"></canvas>

Is this what you want?

Upvotes: 1

Related Questions