HTML5 / Javascript图像加载方法和传递给变量

HTML5/Javascript Image loading method & passing to variable

本文关键字:变量 方法 Javascript 图像 加载 HTML5      更新时间:2023-09-26

我有一些用于加载图像的代码。

var assets = {
    total:0,
    success:0,
    error:0
};
var stillLoading = true;
var img = {};
function LoadImage(name, path){
    var toLoad = new Image();
    toLoad.src = path;
    assets.total++;
    toLoad.addEventListener("load", function(){
        assets.success++;
        console.log(name + " loaded.");
        img[name] = toLoad;
    }, false);
    toLoad.addEventListener("error", function(){
        assets.error++;
    }, false);
};
function Loading(){
    if (assets.success == assets.total){
        if (stillLoading){
            console.log("All assets loaded. Starting game.");
        };
        stillLoading = false;
        return false;
    }else{  
        stillLoading = true;
        return true;
    };
};

可能仍然效率低下,而且很丑陋,因为我是练习javascript的新手,对建议持开放态度。它加载图像并通过函数 Load(( 告诉主程序所有资产何时完成加载,然后将图像添加到对象 img 中。

我已经在我的图像中使用了一段时间,它可以工作。

例如,如果我这样做了。

LoadImage("Car", "imageOfCar.png");
ctx.drawImage(img.Car, 0, 0);

这样可以将图像很好地绘制到画布上。

但是,当我为图像分配另一个变量时,出于各种原因我想这样做,例如将图像分配给对象。

var secondCar = img.Car

然后尝试绘制它。

ctx.drawImage(secondCar, 0, 0);

我收到此错误。

未捕获的类型错误:无法在"CanvasRenderingContext2D"上执行"drawImage":提供的值不是类型"(HTMLImageElement 或 HTMLVideoElement 或 HTMLCanvasElement 或 ImageBitmap(">

如果它适用于初始变量,它应该以相同的方式对刚刚分配完全相同的另一个变量进行操作。那么为什么我会收到此错误?

如果我以典型的方式加载图像,则不会检查它是否已完成加载。

img.Car = new Image();
img.Car.src = "imageOfCar.png";
secondCar = img.Car;
ctx.drawImage(secondCar);

这将起作用。这里的行为有点令人困惑,有人可以向我解释发生了什么,也许可以提出一种解决方法吗?

编辑:只是为了澄清。

这是 html 文件,称为 index.html。

<!DOCTYPE html>
<head>
    <title>HTML5 Game Base</title>
    <link rel = "stylesheet" type = "text/css" href = "styles.css">
</head>
<body>
    <canvas id="screen" width="270" height="480" style="border:1px solid #000000;"></canvas>
    <script src = "script.js"></script>
</body>
</html>

画布设置为screen 。我上面显示的所有 javascript 代码都发生在脚本中.js在 index.html 中调用。

这就是在脚本中调用screen的方式.js。

var canvas = document.getElementById("screen");
var ctx = canvas.getContext("2d");

这就是ctx.drawImage()所指的。

我知道这不是最有用的答案,但我稍微修改了一下你的代码。这是我使用的:

<!DOCTYPE html>
<head>
    <title>HTML5 Game Base</title>
</head>
<body>
    <canvas id="screen" width="270" height="480" style="border:1px solid #000000;"></canvas>
    <script>
    var stillLoading = true;
    var img = {};
    var canvas = document.getElementById("screen");
    var ctx = canvas.getContext("2d");
    assets = {};
    assets.total = 0;
    function LoadImage(name, path){
        var toLoad = new Image();
        toLoad.src = path;
        assets.total++;
        toLoad.addEventListener("load", function(){
            //assets.success++;
            console.log(name + " loaded.");
            img[name] = toLoad;
        }, false);
        toLoad.addEventListener("error", function(){
            assets.error++;
        }, false);
    }
    </script>
</body>
</html>

然后在Chrome的控制台中我输入了

LoadImage("Car", "map.png");
LoadImage("un", "Untitled.png");
ctx.drawImage(img.Car, 0, 0);
ctx.drawImage(img.un, 0, 0);

并获得在画布中加载图像的预期结果。即使将img图像之一分配给新变量,也能按预期工作。

var second = img.Car
ctx.drawImage(second, 0, 0)

手动运行时似乎一切正常,所以我的猜测是时机。何时运行这些命令?它们是在 js 文件中还是从控制台中?

看起来您的加载图像函数很好。抱歉,这不是很有帮助,但希望能帮助您排除不查找问题的位置。

一种方法

是利用Promise,因为new Image的事件是异步的load secondCar当用作setInterval中的参数时可以undefined,例如,load img的事件在调用LoadImage后应用var secondCar = img.Car时可能不完整;还为setInterval添加了变量引用,以便在需要时能够调用clearInterval()

var canvas = document.getElementById("screen");
var ctx = canvas.getContext("2d");
var interval = null;
var assets = {
  total: 0,
  success: 0,
  error: 0
};
var stillLoading = true;
var img = {};
function LoadImage(name, path) {
  return new Promise(function(resolve, reject) {
    var toLoad = new Image();
    assets.total++;
    toLoad.addEventListener("load", function() {
      assets.success++;
      console.log(name + " loaded.");
      img[name] = toLoad;
      // resolve `img` , `assets` object
      resolve([img, assets])
    }, false);
    toLoad.addEventListener("error", function() {
      assets.error++;
      reject(assets)
    }, false);
    toLoad.src = path;
  })
};
function Loading() {
  if (assets.success == assets.total) {
    if (stillLoading) {
      console.log("All assets loaded. Starting game.");
    };
    stillLoading = false;
    return false;
  } else {
    stillLoading = true;
    return true;
  };
};
var promise = LoadImage("Car", "http://pngimg.com/upload/audi_PNG1736.png");
promise.then(function(data) {
  // `data` : array containing `img` , `assets` objects
  console.log(data);
  var secondCar = data[0].Car;
  interval = setInterval(function() {
    if (!(Loading())) {
      ctx.drawImage(secondCar, 0, 0);
    };
  }, 1000 / 60);
});
<canvas id="screen" width="1000" height="700" style="border:1px solid #000000;"></canvas>

已解决。原来这是一个时间问题。在我给出的示例中,当secondCar被分配img.Car时,img.Car尚未加载。

相反,我创建了一个名为 Initialise() 的新函数,并从 Loading() 中调用它。所以从现在开始,我只需要初始化所有可能需要Initialise()内图像的变量。这样,变量只能在加载后分配图像。

新代码:

var canvas = document.getElementById("screen");
var ctx = canvas.getContext("2d");
var assets = {
    total:0,
    success:0,
    error:0
};
var stillLoading = true;
var img = {};
function LoadImage(name, path){
    var toLoad = new Image();
    toLoad.src = path;
    assets.total++;
    toLoad.addEventListener("load", function(){
        assets.success++;
        console.log(name + " loaded.");
        img[name] = toLoad;
    }, false);
    toLoad.addEventListener("error", function(){
        assets.error++;
    }, false);
};
function Loading(){
    if (assets.success == assets.total){
        if (stillLoading){
            console.log("All assets loaded. Starting game.");
            Initialise();
        };
        stillLoading = false;
        return false;
    }else{  
        stillLoading = true;
        return true;
    };
};
LoadImage("Car", "http://pngimg.com/upload/audi_PNG1736.png");
function Initialise(){
    window.secondCar = img.Car;
};

setInterval(function(){
    if (!(Loading())) ctx.drawImage(secondCar, 0, 0);
}, 1000/60);

现在可以工作了,感谢您的帮助,尽管我最终自己解决了它。我仍然希望得到有关如何改进它的任何提示。或者知道我是javascript的新手,任何吹毛求疵都可以帮助我遵守javascript约定。