2015-10-20 106 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:好的部分如果你想知道更多關於這種編碼風格和我爲什麼使用它。 (這是一本很棒的書,即使你不這樣做,我也會推薦它。)