簡體   English   中英

HTML5在帶有for循環的畫布上繪制圖片?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM