簡體   English   中英

使用drawImage()在畫布上繪制多個圖像的問題

[英]Issue drawing multiple Images on Canvas with drawImage()

我只是無法讓它為我工作。

我正在嘗試使用drawImage()將多個圖像繪制到畫布上。 我覺得自己在很大程度上忽略了一些東西。

它應該在畫布上繪制18張卡片。 它將從左側開始50px,從頂部開始向下,並繪制100w * 150h的每張卡片。 每個卡片圖片之間應有25px。 畫布尺寸設置為825w * 600h。

嘗試使用簡單的Javascript(不使用jQuery)完成此任務。 任何幫助表示贊賞。

該圖像是它當前在我的畫布上繪制的方式。 當前如何輸出到畫布。

// Draw the cards to the canvas.
function drawCards()
{
    // Starting positions.
    var x = 50;
    var y = 50;

    // Counter that will hold current card position.
    var cardCount = 0;

    var img = new Image(100, 150);

    // How many rows.
    for (var row = 0; row < 3; row++)
    {
        // How many columns.
        for (var column = 0; column < 6; column++)
        {
            // Store the current card.
            var card = memoryDeck[cardCount];

            // Check if the card is flipped, if it is set an image with url to face card.
            if (card.flipped == true)
            {
                img.onload = function() {
                    ctx.drawImage(this, x, y, 100, 150);
                }
                img.src = card.faceImage;
            }
            // Otherwise set image url to back of card.
            else
            {
                img.onload = function() {
                    ctx.drawImage(this, x, y, 100, 150);
                }
                img.src = card.backImage;           
            }

            // Increase the x position (the width of a card, plus the space in between), and the current card position being stored.
            x += 125; 
            cardCount++;
        }

        // We are on a new row, reset the column card position and increase the row card position.
        x = 50;
        y += 175;
    }
}

JS變量的作用域不是阻塞,而是作用域。 因此,當img.onload訪問xy ,它們引用xy的最終值。 要創建塊作用域變量,請使用let語句或IIFE。

// Draw the cards to the canvas.
function drawCards()
{
    // Starting positions.
    var x = 50;
    var y = 50;

    // Counter that will hold current card position.
    var cardCount = 0;

    var img = new Image(100, 150);

    // How many rows.
    for (var row = 0; row < 3; row++)
    {
        // How many columns.
        for (var column = 0; column < 6; column++)
        {
            // Store the current card.
            var card = memoryDeck[cardCount];

            // Check if the card is flipped, if it is set an image with url to face card.
            if (card.flipped == true)
            {
                (function(x, y) {
                img.onload = function() {
                    ctx.drawImage(this, x, y, 100, 150);
                }
                img.src = card.faceImage;
                })(x, y);
            }
            // Otherwise set image url to back of card.
            else
            {
                (function(x, y) {
                img.onload = function() {
                    ctx.drawImage(this, x, y, 100, 150);
                }
                img.src = card.backImage; 
                })(x, y);          
            }

            // Increase the x position (the width of a card, plus the space in between), and the current card position being stored.
            x += 125; 
            cardCount++;
    }

        // We are on a new row, reset the column card position and increase the row card position.
        x = 50;
        y += 175;
     }

}

一個類似的簡單問題是:

 READ THE SOURCE CODE! <script> function demo1() { for (var i = 0; i <= 5; i++) { setTimeout(function(){alert('i === ' + i)}, i * 200); } // i === 6 // You expect this to happen: // [alerts "i === 1"] // [alerts "i === 2"] // [alerts "i === 3"] // [alerts "i === 4"] // [alerts "i === 5"] // What actually happens: // [alerts "i === 6"] // [alerts "i === 6"] // [alerts "i === 6"] // [alerts "i === 6"] // [alerts "i === 6"] // [alerts "i === 6"] } </script> <button onclick="demo1();">Demo 1 </button> <script> function demo2(){ for (var i = 0; i <= 5; i++) { // IIFE for the win! (function(i) { setTimeout(function(){alert('i === ' + i)}, i * 200); })(i); } // Expected: // [alerts "i === 0"] // [alerts "i === 1"] // [alerts "i === 2"] // [alerts "i === 3"] // [alerts "i === 4"] // [alerts "i === 5"] // Actual: // [alerts "i === 0"] // [alerts "i === 1"] // [alerts "i === 2"] // [alerts "i === 3"] // [alerts "i === 4"] // [alerts "i === 5"] } </script> <button onclick="demo2();">Demo 2</button> 

給定的答案是有問題的,因為它在循環中聲明了函數調用。 這種聲明方式很危險,如果您不了解閉包,可能會導致內存泄漏。 用於克服范圍問題的方法效率也很低。 而且該代碼將不起作用,因為僅創建了一個圖像,並且每次設置src時,都會取消先前的加載src並重新開始該過程。

另外,創建匿名函數會使調試代碼更加困難,因為任何錯誤都將使跟蹤變得困難,並且分析也將難以閱讀。 始終命名函數,並將函數始終放在其作用域的頂部。

function drawCards(){
    // declare all variables and functions
    var row, column, src, cardIndex, card;
    function loadThenDisplayImage (src, x, y) {
        var image;
        function onImageload () {
             ctx.drawImage(this, x, y, cardW, cardH);
        }
        image = new Image(cardW, cardH);
        image.src = src;
        image.onload = onImageLoad;
    }
    // define constants and variables.
    const left = 50;
    const top = 50;
    const cardW = 100;
    const cardH = 150;
    const xSpacing = 25;
    const ySpacing = 25;
    cardIndex= 0;

    // function logic 
    for (row = 0; row < 3; row += 1) {
        for (column = 0; column < 6; column += 1) {
            card = memoryDeck[cardIndex += 1];
            scr = card.flipped ? card.faceImage : card.backImage;
            loadThenDisplayImage(  // long function call best split for readbility
                src, 
                left + (cardW + xSpacing) * column, 
                top + (cardH + ySpacing) * row
            );
        }
     }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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