簡體   English   中英

HTML5畫布上的drawImage無法正常工作

[英]drawImage on HTML5 canvas is not working

我正在創建一個“捕捉掉落物品”游戲,並且已經成功地將“捕捉”圖像和“掉落物品”圖像繪制到了畫布上。 但我也想在未捕獲到掉落的圖像並擊中html5畫布的底部時顯示圖像(x.png)。 當動畫圖像下降到畫布的底部時,從動畫函數調用generateX函數。 sound.play()正在工作。 generateX函數中的console.logs記錄以下內容-2,3 | 1,3 | 1,3-因此我知道該函數在第一次運行時未完全加載圖像。 除了實際顯示的圖像外,一切似乎都可以正常工作。 我試圖以其他線程建議的方式構建它,但沒有任何效果。 任何幫助深表感謝!

generateX: function() {
    console.log('inside generateX func');
    var imgX = new Image();
    imgX.src = 'assets/x.png';
    function drawX() {
        console.log(3);
        counter+=20;
        context.drawImage(imgX, xIcon.x + counter, xIcon.y, xIcon.width, xIcon.height);
        xArr.push(imgX);
        console.log('xArr', xArr);
    }
    if (imgX.complete) {
        console.log(1);
        drawX();
    } else {
        console.log(2);
        imgX.onload = drawX;
    }
        helper.checkMisses();
}

animate: function() {
    var sound;
    if (continueAnimating) {
        requestAnimationFrame(helper.animate);
    }
    for (var i = 0; i < surveys.length; i++) {
        var survey = surveys[i];
        if (helper.isColliding(survey, dinoSaurus)) {
            sound = new Audio("audio/coinSound.mp3");
            sound.play();
            score += 5;
            helper.resetSurvey(survey);
        }
        survey.y += survey.speed;
        // if the survey is below the canvas,
        if (survey.y > canvas.height) {
            sound = new Audio("audio/buzzerSound.mp3");
            sound.play();
            helper.generateX();
            helper.resetSurvey(survey);
        }
    }
    // redraw everything
    helper.drawAll();
}

-

resetSurvey: function(survey) {
    // randomly position survey near the top of canvas
    survey.x = Math.random() * (canvas.width - surveyWidth);
    survey.y = 40 + Math.random() * 30;
    survey.speed = (0.55 + Math.random()) * 0.9;
}

嘗試更早加載圖像

如果我正確理解了您的情況,我認為問題在於您需要更早加載圖像,以便在要繪制圖像時可以很容易地准備好圖像,而不是只等在generateX內部加載它。 當前的編碼方式是,加載圖像( imgX.src = ... ),然后立即嘗試繪制它。 是的,您正在檢查加載是否完成,如果沒有完成,請稍后再試。 但是,更好的策略是更早地加載圖像,例如在游戲初始化期間。

演示版

下面的代碼片段演示了這樣做的區別。 它加載2個不同的圖像。 兩者之間的唯一區別是,一個(在左側)被提前加載而另一個(在右側)僅被加載到generateX內部。 前一個圖像在游戲周期中第一次正確顯示,而后一個圖像在第一次游戲中丟失,僅在第二次顯示正確。

 function loadLeftImageWellBeforeRunningGenerateX() { // correct timing imgs[0] = new Image(); imgs[0].src = 'http://placehold.it/200x100.png'; } function loadRightImageInsideGenerateX() { // incorrect timing imgs[1] = new Image(); imgs[1].src = 'http://placehold.it/100x50.png'; } function generateX() { loadRightImageInsideGenerateX(); log('--inside generateX func'); imgs.forEach(function(imgX, num) { // same as your original code, just done for 2 different images if (imgX.complete) { log("----image #" + num + " (" + side[num] + "); " + 1 + ", ie image complete"); drawX(imgX, num); } else { log("----image #" + num + " (" + side[num] + "); " + 2 + ", ie image not complete"); imgX.onload = drawX(imgX, num); } }); } function drawX(imgX, num) { // same as your original code, just allows placement of 2 images side-by-side log("----image #" + num + " (" + side[num] + "); " + 3 + ", ie drawing image (" + prefix[num] + "successfully)"); context.drawImage(imgX, num * 150 + 10, 10, 100, 50); if (num === 1) {prefix[1] = "";} } var imgs = [], numClicks = 0, side = ["left", "right"], prefix = ["", "un"], button = document.querySelector("button"), canvas = document.getElementById('myCanvas'), context = canvas.getContext('2d'); context.fillStyle = "yellow"; context.fillRect(0, 0, 300, 150); // as far as game logic goes, the only important lines below are marked with arrows // the rest is just "fluff" to make the demo more understandable to the user button.addEventListener("click", function() { numClicks += 1; if (numClicks === 1) { log("You must clear your browser's recent cache every time you run this snippet " + "in order for it to demonstrate the problems and solutions " + "associated with loading images in this code."); button.innerHTML = "Clear browser cache and click here again to start game initialization"; } else if (numClicks === 2) { loadLeftImageWellBeforeRunningGenerateX(); // <----- *** log("Game initializes. No images should yet be visible, " + "but image #0 (left) should be loading/loaded now, ie ahead of time. " + "Image #1 (right) is not yet loading/loaded. Click again to 'play game'."); button.innerHTML = "Do NOT clear the browser cache and click here again to start playing game"; } else { button.innerHTML = "Do NOT clear the browser cache and click here again to continue playing game"; if (numClicks === 3) { log("Game begins. Images are required for the first time. Only the pre-loaded left image shows " + "even though loading both is attempted."); } else { log("Game continues. On second and subsequent re-draws, both images are now available and visible."); } generateX(); // <----- *** } }); function log(msg) { document.body.appendChild(document.createElement("p")).innerHTML = msg; } 
 p { margin: 0.2em; } 
 <canvas id="myCanvas" width="300" height="80"></canvas> <div> <button>Click here to begin demo</button> </div> 

您瀏覽器的緩存可以隱藏此錯誤

順便說一句,如果並且當您嘗試調試此類錯誤時,請注意許多/大多數/所有瀏覽器都會緩存圖像,如果您不知道正在發生什么,則可能很難復制此類錯誤。 例如,您可能會運行錯誤代碼,並且在整個游戲周期中第一次丟失圖像。 您研究代碼,進行更改以嘗試修復該錯誤並再次運行該代碼。 瞧,問題似乎已經解決,因為圖像現在是整個游戲周期中的第一次。 但是,實際上,它可能只在第一個周期中出現,這不是因為錯誤已修復,而是因為瀏覽器即使在第一個游戲周期中也能夠使用緩存的圖像,從而無需從源代碼中加載它。 簡而言之,如果您要嘗試調試這樣的問題,即您懷疑文件加載的時機很重要,但該錯誤僅在某些時候出現,請嘗試清除瀏覽器的最新緩存以查看是否使該錯誤更加明顯。

清除瀏覽器的緩存:

  • Firefox(對於Mac或Windows,為v44 ...):單擊“歷史記錄” /單擊“清除最近的歷史記錄...” /如有必要,單擊以打開“詳細信息” /選中“緩存” /單擊“立即清除”
  • Chrome(對於Mac,v48 ...)“ Chrome”(左側菜單項)/“清除瀏覽數據...” /選擇“緩存的圖像和文件” /單擊“清除瀏覽數據”
  • Chrome瀏覽器(適用於Windows,v48 ...)單擊自定義和控制圖標(在右側)/單擊“更多工具...” /單擊“清除瀏覽數據...” /單擊“清除瀏覽數據”
  • Internet Explorer(對於Windows,v11 ...)單擊“工具” /單擊“刪除瀏覽歷史記錄” /選擇“下載歷史記錄” /單擊“刪除”

暫無
暫無

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

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