【问题标题】:Drawing an image in javascript won't work when vars are global当变量是全局变量时,在 javascript 中绘制图像将不起作用
【发布时间】:2014-02-13 10:12:02
【问题描述】:

嘿,我想画多张图片,一张是画布背景,两张是可以在画布上移动的播放器。这是我的问题:当我将 var canvas 和 canvas 属性放在全局范围内时,它不起作用。但是当我把它放回 img.onload 函数时,它就可以工作了!!!为什么会这样?我有哪些选择?

var canvas = document.getElementById("Canvas");
 canvas.width = 500;     
 canvas.height = 500;
 var g = canvas.getContext("2d");

var img = new Image();   
img.src = "Images/Grass Texture.png";

var player1 = new Image();   
player1.src = "Images/Players/Mignolet.png";

var player2 = new Image();   
player2.src = "Images/Players/De Gea.png";

var football = new Image();   
football.src = "Images/Football/Football.png";

img.onload = function()
{
   /* The rest of the code draws onto the graphics context */
   g.drawImage(img, 0, 0);
   g.drawImage(img,1200, 1200, 1200, 1200); 
};

【问题讨论】:

    标签: javascript image canvas


    【解决方案1】:

    了解图片加载是异步的很重要。这意味着当您的图像正在加载时,代码将继续运行。

    如果浏览器无法及时加载和解码图像,则不会有任何图像可绘制。

    即使您使用onload 处理程序(这是必要的),您也需要考虑其余代码中的异步性质 - 可能代码继续到其他部分,由于依赖于图像而失败。

    您可以像这样收集图像加载:

    ...
    
    /// if you have many images an array could be considered    
    var img = new Image();   
    var player1 = new Image();   
    var player2 = new Image();   
    var football = new Image();   
    
    /// number of images to load
    var count = 4;
    
    /// now share a load handler
    img.onload      = loadHandler;
    player1.onload  = loadHandler;
    player2.onload  = loadHandler;
    football.onload = loadHandler;
    
    /// set sources to start loading
    img.src      = "Images/Grass Texture.png";
    player1.src  = "Images/Players/Mignolet.png";
    player2.src  = "Images/Players/De Gea.png";
    football.src = "Images/Football/Football.png";
    
    function loadHandler() {
    
        /// decrement the counter
        count--;
    
        /// when 0 all images has loaded
        if (count === 0) startGame();
    }
    

    当所有图像加载完毕后,脚本将继续运行到startGame(),这也是您需要继续游戏的地方:

    function startGame() {
        ...
        g.drawImage(img, 0, 0);
        g.drawImage(img,1200, 1200, 1200, 1200); 
    
        /// Important! continue your code from here
        nextStep();
    }
    

    因此,在通过设置源调用图像加载后,您的脚本不会调用任何其他步骤,直到调用 startGame()

    现在,由于各种原因,加载可能会失败。如果您不处理错误,您的游戏可能会停止,您将不知道为什么。在开发过程中,您当然应该始终检查控制台是否有错误(如果发生任何错误,请参阅控制台、网络等),但对于用户而言,这无济于事。

    您也应该始终为图像添加错误处理机制。您可以通过使用onerroronabort 处理程序来做到这一点 - 在设置onload 处理程序之后:

    var hasErrors    = false;
    
    img.onerror      = errorHandler;
    player1.onerror  = errorHandler;
    player2.onerror  = errorHandler;
    football.onerror = errorHandler;
    
    img.onabort      = errorHandler;  /// or use a separate abort handler
    player1.onabort  = errorHandler;
    player2.onabort  = errorHandler;
    football.onabort = errorHandler;
    

    在错误处理程序中,您可以通知用户,或使用回退,或任何可能解决问题的方法:

    function errorHandler(err) {
    
        /// set error flag
        hasErrors = true;
    
        /// notify user, post an error message etc. something..
        console.log('Could not load image:', this.src, err);
    
        /// call loadHandler() from here to decrement counter and
        /// handle situation when all images has reported in for duty (or not)
        loadHandler();
    }
    

    然后修改loadHandler 以识别错误(这里只是一个警告,但替换为更有用的东西):

    function loadHandler() {
    
        /// decrement the counter
        count--;
    
        /// when 0 all images has loaded
        if (count === 0) {
            if (hasErrors) {
                alert('Sorry mate! Error during image loading');
                return;
            }
            startGame();
        }
    }
    

    话虽如此,您也可以通过使用可以为您处理所有设置和事件(加载、错误、进度等)的图像加载器来执行此操作。这些是制造的,包括。如果可以的话,我自己的,YAIL loader(还有其他人),目的是让开发人员免于很多问题和头痛 - 他们是免费的。需要考虑的事情..

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      • 2019-07-27
      • 2013-07-13
      • 1970-01-01
      相关资源
      最近更新 更多