2015-10-20 107 views
0

我试图将一堆图像加载到画布上,但不是它们出现。源代码包含我想要使用的图像的链接。有人有主意吗?Javascript(帆布) - for循环和drawImage不一起工作

这是我第一次使用画布。

<canvas id ="canvas" width = "500" height = "500"></canvas> 
    <script> 

    var c = document.getElementById("canvas"); 
    var ctx = c.getContext("2d"); 

    loadImages(ctx); 

    function loadImages() 
    { 
     var c = document.getElementById("canvas"); 
     var ctx = c.getContext("2d"); 

      var number = 0; 
      var bX = 0; 
      var bY = 0; 
      var images = []; 
      images = getImages(); 

      for(var i = 0;i<images.length;i++){ 
       var t = images[i]; 
       document.write(t.src+"<br>"); 
       ctx.drawImage(t,0,0,100,100); 
       if(i%4==0) 
       { 
        bX = 0; 
        bY -= 110; 
       } 
       else 
       { 
        bX+=110; 
       } 

      } 

    } 

我做了这个功能,预载的图片,并在阵列

function getImages() 
    { 
     var imgList = []; 
     var sources = 
     [    "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_00.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_01.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_02.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_03.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_04.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_05.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_06.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_07.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_08.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_09.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_10.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_11.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_12.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_13.png", 
         "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_14.png" ]; 
      var s = 0; 
      var length = sources.length; 
      for(s; s< length;++s) 
      { 
       imgList[s] = new Image(); 
       imgList[s].src = sources[s]; 
      } 
      return imgList; 
     } 


    </script> 
</body> 



</html> 
+0

看来你打算使用bX和BY作为'drawImage'的参数。第一次满足条件时,使用'bY - = 110'会使bY为负,这是自0%0 == 0以来的第一次迭代。 –

+1

不要使用'document.write',[它有很多问题](https://www.youtube.com/watch?feature=player_detailpage&v=Y2Y0U-2qJMs#t=1082s),并且有更好的选择。如果您只是将其用于调试,请改用'console.log'。“document.write”存在的一个问题是,如果在加载页面后调用它,它将清除页面上的所有内容并将其替换。这意味着,如果在页面加载后调用'loadImages',则包含画布标签*的所有内容都将丢失,因此您的代码将停止工作。 –

回答

0

的问题是图像加载的arent尝试在绘制之前归还。您应该创建IMGS并追加到身体

images = getImages(); 

for(var i = 0; i<images.length; i++){ 
    var img = document.createElement("img"); 
    img.src= images[i].src; 
    document.body.appendChild(img); 
    img.style.display = "none"; 
    img.id="img"+String(i); 
} 

然后绘制他们这样

loadImages(images); 

function loadImages(images){ 
    var c = document.getElementById("canvas"); 
    var ctx = c.getContext("2d"); 

    for(var i = 0;i<images.length;i++){ 
      ctx.drawImage(document.getElementById("img"+String(i)),i*10,0,100,100); 
      if(i%4==0) 
      { 
       bX = 0; 
       bY -= 110; 
      } 
      else 
      { 
       bX+=110; 
      } 

     } 

} 

我测试了它和它的工作全部

+0

也将名称loadImages更改为drawImages,这是更系数,图像加载时附加到身体,然后绘制到画布上 –

+0

'“img”+ i'将胁迫'我'字符串,你不真的需要使用'String'构造函数。它只是增加了更多的噪音,使代码难以阅读。它也使脚本更长(因此它会下载更慢)。 –

+0

此外,在将图像元素添加到DOM之前,将其绘制到画布上并不能保证图像在您尝试绘制之前完成下载。图像加载是异步的。 –

1

首先,确保图像检索并正确加载。然后调整你的代码类似下面:

for (var i = 1; i <= images.length; i++) { 
     var t = images[i]; 
     document.write(t.src+"<br>"); 
     ctx.drawImage(t,bX,bY,100,100); 
     if (i%4 === 0) { 
      bX = 0; 
      bY += 110; 
     } 
     else { 
      bX += 110; 
     } 
    } 

你想从索引1而不是0迭代,从而使if语句i % 4 === 0没有被满足了蝙蝠的权利。然后,您要使用变量bXbY作为图像的位置偏移量。您之前使用过ctx.drawImage(t,0,0,100,100);,将所有图像堆叠在同一位置。最后,增加bY为了推下图像。

0

由于在尝试使用它们之前并未等待图像加载,因此无法正常工作。您可以使用Image对象的load event执行此操作。我会写这样的东西,使用Promise s来管理加载状态。

var images, 
    nameList = document.getElementById('image-names'), // just a div to display the stuff you were writing out to document. write. 
    // this function returns a Promise which will resolve once all of the 
    // images are done loading 
    preloadImages = function() { 
    var imagePromises, 
     sources = [ 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_00.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_01.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_02.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_03.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_04.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_05.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_06.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_07.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_08.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_09.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_10.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_11.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_12.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_13.png", 
     "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_14.png" 
    ]; 

    // if we have already loaded and cached the images, 
    // return them right away wrapped in a resolved Promise 
    if (images) { 
     nameList.innerHTML += 'Using cached images.<br>'; 
     return Promise.resolve(images); 
    } 

    // otherwise we use .map to iterate over the items in sources and 
    // create a new array of promises and store them in imagePromises 
    imagePromises = sources.map(function (src) { 
     // each of the promises that are created by this function 
     // are stored in imagePromises and will resolve when the image 
     // it represents fires its load event 
     return new Promise(function (resolve, reject) { 
      var img = new Image(); 

      // once the image has loaded, resolve its Promise 
      img.onload = function() { 
      resolve(img); 
      }; 
      // if there is an error reject this image's Promise 
      img.onerror = function() { 
      reject(src + ' failed to load.'); 
      }; 

      img.src = src; 
     }); 
    }); 

    // Promise.all will create a Promise that will resolve when all of the 
    // images are loaded (because all of the Promises representing those 
    // images will have resolved). If there is an error loading any of the 
    // images it will be rejected, which we can handle later. 
    return Promise.all(imagePromises) 
     // after Promise.all returns a resolved Promise, we create a new Promise 
     // using .then, which is what actually gets returned by preloadImages. 
     .then(function (loadedImages) { 
     // cache the loaded images in case we need them later 
     images = loadedImages; 
     // return the images so that anything chained off of this Promise 
     // has access to them. 
     return loadedImages; 
     }); 

    }, 
    displayImages = function() { 
    var c = document.getElementById("canvas"), 
     ctx = c.getContext("2d"), 
     bX = 0, 
     bY = 0; 

    // preloadImages will return a Promise that will resolve once all of the 
    // images have been loaded. The .then chained off of that Promise receives 
    // the list of images via the images parameter 
    preloadImages().then(function (images) { 
     var i, 
     img; 

     for(i = 0; i < images.length; /* no increment expression, see below */) { 
      img = images[i]; 
      nameList.innerHTML += img.src + "<br>"; 
      ctx.drawImage(img, bX, bY, 100, 100); // you need to make sure to 
               // use your offset here 

      // incrementing here instead of in the increment expression of 
      // for statement makes this part work correctly 
      i += 1; 

      if (i % 4 === 0) { 
       bX = 0; 
       bY += 110; 
      } else { 
       bX += 110; 
      } 
     } 
    }).catch(function (msg) { 
     // if there was an error loading any of the images, this .catch 
     // will display an error 
     nameList.innerHTML += msg + '<br>'; 
    }); 
}; 

displayImages(); 

有一个working fiddle here。如果将不存在的图像添加到源列表中,您会注意到它显示的是错误消息,而不是绘制到画布上。

您不必使用Promises,而是可以让preloadImages将回调作为参数,然后在所有图像加载后调用该参数。在这种情况下,您必须手动跟踪已加载的图像数量,并在每个图像的load事件中检查是否在调用回调之前加载了所有图像。

我的编码风格可能看起来有点奇怪,因为我习惯于使用function expressions instead of function statements以及像严格等号运算符(===)这样的其他一些东西。我会推荐Douglas Crockford的书JavaScript:好的部分如果你想知道更多关于这种编码风格和我为什么使用它。 (这是一本很棒的书,即使你不这样做,我也会推荐它。)