[英]HTML5 drawing pictures on a canvas with a for loop?
所以,我想用HTML5創建一個Minecraft網站主題。 我在HTML5 / Javascript中有點搖搖欲墜(暫時沒用過它),我需要一些幫助。 我正在嘗試計算一些可以放在屏幕上的16x16px瓷磚。 然后,隨機“生成地圖”作為屏幕背景。 然后,我使用相同的2 for循環生成地圖,用填充圖塊填充屏幕(在生成過程中分配圖片路徑)。 問題是,畫布完全是白色的。 任何人都可以選擇問題,並在可能的情況下給我任何提示嗎? 提前致謝! 這是我的HTML5代碼:
<!DOCTYPE html>
<html>
<head>
<title>Minecraft Background Check</title>
</head>
<body>
<canvas id="bg" style="position:fixed; top:0; left:0; border:1px solid #c3c3c3; width: 100%; height: 100%;"></canvas>
<script type="text/javascript">
"use strict";
var c = document.getElementById("bg");
var ctx = c.getContext("2d");
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
var width = Math.ceil(window.innerWidth / 16);
var height = Math.ceil(window.innerHeight / 16);
for (var x=0;x<width;x++)
{
for(var y=0;y<height;y++)
{
var rand = Math.floor(Math.random()*11);
var texLoc = getImageNameFromRand(rand,y,height);
var img=new Image();
img.onload = function(){
return function() {
ctx.drawImage(img,x*16,y*16);
};
};
img.src=texLoc;
}
}
function getImageNameFromRand(rand,yVal,maxY)
{
var dirt = 'dirt.png';
var stone = 'stone.png';
var cobble = 'cobble.png';
var mosscobble = 'mosscobble.png';
var bedrock = 'bedrock.png';
if(yVal===0)
{
return dirt;
} else if(yVal<3)
{
if(rand < 7) {
return dirt; }
else {
return stone; }
} else if(yVal<5)
{
if(rand < 4) {
return dirt; }
else {
return stone; }
} else if(yVal<maxY-2)
{
if(rand === 0) {
return dirt; }
else if(rand < 4) {
return cobble; }
else if(rand < 5) {
return mosscobble; }
else {
return stone; }
} else if(yVal<maxY-1)
{
if(rand < 4) {
return bedrock; }
else {
return stone; }
} else if(yVal<maxY)
{
if(rand < 7) {
return bedrock; }
else {
return stone; }
} else {
return bedrock; }
return bedrock;
}
</script>
</body>
</html>
這里有很多解釋。 我測試了下面的代碼,並讓它工作,但我只是一遍又一遍地使用一個圖像。 希望這可以在與您的代碼合並時使用。 將代碼放在下面,代替for循環(即在var高度之后和函數getImageNameFromRand之前)。
首先,您的代碼定義了全局命名空間中的所有變量,因此每次通過原始循環時都會替換img var,以及它的src和onload函數等。 此外,增加for循環的x和y在onload函數中通過閉包引用,但由於它們僅在外部循環(而不是onload函數)中遞增,因此它們在onload調用期間都被設置為它們的結束值(原始循環運行時的結束值)。
另外,嘗試將所有腳本放入匿名函數中,如(function(){YOUR CODE HERE})()。 這樣您就不會使用本地變量添加到全局命名空間,並且onload將因為閉包而具有所需的內容。 我測試了將所有內容放入匿名函數中,它對我有用。
希望我能正確地復制和粘貼這一切。 請評論是否關閉。 祝好運!!!
//Copy this code in place of your original "for" loop:
var imgs = [];
var imgIndex = 0;
for (var x = 0; x < width; x++){
for(var y = 0; y < height; y++){
var rand = Math.floor(Math.random() * 11);
var texLoc = getImageNameFromRand(rand, y, height);
imgs[imgIndex] = new Image();
imgs[imgIndex].onload = (function () {
var thisX = x * 16;
var thisY = y * 16;
return function () {
ctx.drawImage(this, thisX, thisY);
};
}());
imgs[imgIndex].src = texLoc;
imgIndex += 1;
}
}
執行以下操作時:
img.onload = function(){
return function() {
ctx.drawImage(img,x*16,y*16);
};
};
您正在嘗試在img
上創建一個閉包,以便在onload
處理程序內部引用您在循環迭代中創建的圖像。
但你並沒有這么做。 相反, onload
處理程序只是定義一個匿名函數,然后什么都不做。
img.onload = function(img){
return function() {
ctx.drawImage(img,x*16,y*16);
};
}(img);
如果您更改它以便立即調用匿名函數並傳入img
,那么您將關閉img
(來自for
循環上下文)並且它將執行您想要的操作。
如果沒有立即調用外部匿名函數,那么它將成為圖像的onload處理程序。 什么都不會發生。 通向空白畫布。
問題是,在你的循環,你一遍又一遍地繪制的圖像, 在彼此的頂部 。 如果在第一次運行后完全脫離forloops(x = 0,y = 0),您將在位置0,0上看到隨機圖像的單個圖塊。 當它遍歷整個double for循環時,最后一個圖像將繪制在畫布的底角,這將創建您正在看到的“空白白色畫布”。 你需要讓它繪制一個隨機瓷磚的“預填充”畫布。 這也意味着你的for循環需要在onload()函數中,因為你的背景只被繪制一次,而不是幾百次/幾千次。
尋找html5畫布圖案/瓷磚然后從那里工作。
另外,你的onload函數不需要inside函數,你可以像這樣:
img.onload = function(){
// - nested for loops
// -> generate a tile pattern to fit the entire canvas
// - ctx.drawImage()
};
祝好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.