0

What I am trying to do is load images dynamically and then draw them on the screen. However, when I call console.log(images), it is empty.

Here is the code:

if (canvas.getContext)
{
  var ctx = canvas.getContext("2d");
  var images = new Array();
  for (i = 0; i < mattes_array.length; i++)
  {
    var imgsrc = mattes_array[i]["imgsrc"];
    var total_size = mattes_array[i]["total_size"];
    var cpu = mattes_array[i]["cpu"];
    var cid = mattes_array[i]["cid"];

    var imageObj = new Image();
    imageObj.onload = function() {
      images[i] = imageObj;
      console.log(images[i]);
    };
    imageObj.id = "matte_" + cid;
    imageObj.src = imgsrc;

  }

  console.log(images); //this is empty
  for (i = 0; i < mattes_array.length; i++)
  {
    var imgsrc = mattes_array[i]["imgsrc"];
    var total_size = mattes_array[i]["total_size"];
    var cpu = mattes_array[i]["cpu"];
    var cid = mattes_array[i]["cid"];

    var pattern = ctx.createPattern(images[i], 'repeat');
    ctx.strokeStyle = pattern;
    ctx.lineWidth = width - opening_width - (total_size * 2);
    ctx.strokeRect(0, 0, width, height);
  }
}

I have also tried doing it in one loop, but it seems to only draw the last image:

if (canvas.getContext)
{
  var ctx = canvas.getContext("2d");
  var images = new Array();
  for (i = 0; i < mattes_array.length; i++)
  {
      var imgsrc = mattes_array[i]["imgsrc"];
      var total_size = mattes_array[i]["total_size"];
      var cpu = mattes_array[i]["cpu"];
      var cid = mattes_array[i]["cid"];


      var imageObj = new Image();
      imageObj.onload = function() {
        var pattern = ctx.createPattern(imageObj, 'repeat');
        ctx.strokeStyle = pattern;
        ctx.lineWidth = width - opening_width - (total_size * 2);
        ctx.strokeRect(0, 0, width, height);
      };
      imageObj.id = "matte_" + cid;
      imageObj.src = imgsrc;

  }
}

Here is an image of what I am trying to do:

enter image description here

AllisonC
  • 2,973
  • 4
  • 29
  • 46
  • Is console.log(images[i]); also empty? The one inside your for-loop – DannyThunder Dec 04 '13 at 15:07
  • No, it displays the image data of only one of the images, but it does this 3 times (there are 3 total images) – AllisonC Dec 04 '13 at 15:10
  • I'm also getting weird results when doing console.log(i) inside the onload function - I get 0, 0, 38 on one test and 0, 0, 0 on another test – AllisonC Dec 04 '13 at 15:13
  • Your second example: you see the last image because `width`, `opening_width` and `height` is the same for all. There is no any change in `for` loop. You are drawing them one upon another. And for the 1st example is similar. – Anto Jurković Dec 04 '13 at 16:02
  • But it works correctly when I use colors for the stroke style instead of an image. – AllisonC Dec 04 '13 at 16:09
  • The only variable value in `ctx.lineWidth = width - opening_width - (total_size * 2);` is `total_size`. What are values of `mattes_array[i]["total_size"];` – Anto Jurković Dec 04 '13 at 16:30
  • mattes_array[0]: 0; mattes_array[1]: 7.5; mattes_array[2]: 15 – AllisonC Dec 06 '13 at 20:41

1 Answers1

0

Images load asynchronously. You're trying to draw them before they are loaded. Give this a try:

if (canvas.getContext)
{
  var ctx = canvas.getContext("2d");
  var images = new Array();
  var loaded = 0;
  for (i = 0; i < mattes_array.length; i++)
  {
    var imgsrc = mattes_array[i]["imgsrc"];
    var total_size = mattes_array[i]["total_size"];
    var cpu = mattes_array[i]["cpu"];
    var cid = mattes_array[i]["cid"];

    var imageObj = new Image();
    imageObj.onload = function() {
      images[i] = imageObj;
      console.log(images[i]);
      if ( ++loaded === mattes_array.length ) onloaded();
    };
    imageObj.id = "matte_" + cid;
    imageObj.src = imgsrc;

  }

  function onloaded() {
    console.log(images); //this is won't be empty anymore
    for (i = 0; i < mattes_array.length; i++)
    {
      var imgsrc = mattes_array[i]["imgsrc"];
      var total_size = mattes_array[i]["total_size"];
      var cpu = mattes_array[i]["cpu"];
      var cid = mattes_array[i]["cid"];

      var pattern = ctx.createPattern(images[i], 'repeat');
      ctx.strokeStyle = pattern;
      ctx.lineWidth = width - opening_width - (total_size * 2);
      ctx.strokeRect(0, 0, width, height);
    }
  }
}
kalley
  • 18,072
  • 2
  • 39
  • 36
  • I had to use something called "closure", like in this post http://stackoverflow.com/questions/15587330/test-if-all-images-are-loaded. It is still only loading one image though (either the first or the last, I can't tell because they are the same) – AllisonC Dec 06 '13 at 20:58
  • This is what I did: var imageObj = new Image(); imageObj.onload = (function(i){ images[i] = imageObj; return function(){ console.log(i); console.log(images[i]); if ( ++loaded === mattes_array.length ) onloaded(); } })(i); imageObj.id = "matte_" + cid; imageObj.src = imgsrc; – AllisonC Dec 06 '13 at 21:21