JavaScript - 未捕获TypeError:输入错误

时间:2012-07-18 11:15:03

标签: javascript jquery html5

我正在尝试打破spritesheet,好吧,它不会像它应该的那样将它放入2D数组中。在我的代码结束时,在console.log附近,它会吐出ImageData ...但是当它尝试putImageData时......我得到Uncaught TypeError: Type error

帮助?

这是我的代码:

$(document).ready(function () {
    console.log("Client setup...");
    canvas = document.getElementById("canvas");
    context = canvas.getContext("2d");
    canvas.tabIndex = 0;
    canvas.focus();
    console.log("Client focused.");

    var imageObj = new Image();
    imageObj.src = "./images/all_tiles.png";
    imageObj.onload = function() {
    context.drawImage(imageObj, imageWidth, imageHeight);
    };

    var allLoaded = 0;
    var tilesX = ImageWidth / tileWidth;
    var tilesY = ImageHeight / tileHeight;
    var totalTiles = tilesX * tilesY;        
    var tileData = [totalTiles]; // Array with reserved size
    for(var i=0; i<tilesY; i++)
    {
      for(var j=0; j<tilesX; j++)
      {           
        // Store the image data of each tile in the array.
        tileData.push(context.getImageData(j*tileWidth, i*tileHeight, tileWidth, tileHeight));
        allLoaded++;
      }
    }

    if (allLoaded == totalTiles) {
    console.log("All done: " + allLoaded);
    console.log(tileData[1]);
    context.putImageData(tileData[0], 0 ,0); // Sample paint
    }


});

错误发生在context.putImageData(tileData[0], 0 ,0); // Sample paint

以上是http://jsfiddle.net/47XUA/

以上代码的示例

5 个答案:

答案 0 :(得分:4)

您的问题是tileData的第一个元素不是ImageData对象,它是一个简单的数字!初始化阵列时,您使用了:

var tileData = [totalTiles];

这意味着tileData[0]等于totalTiles的值,即483。您向ImageData提供了一个数字而不是putImageData对象,并且浏览器在混乱中抛出错误。如果你查看数组其余部分中的任何其他元素,你会看到它已成功填充了ImageData个对象,如你所愿;只有数组中的第一个元素是数字。

你可能打算这样做:

var tileData = new Array(totalTiles);

将创建具有指定length属性的数组,而不是将数组中的第一个值设置为数字。就个人而言,我会进行一些性能测试,看看它是否有用;你也可以使用var tileData = [];

答案 1 :(得分:3)

当传入语句的变量或对象不是该命令所期望的类型且无法转换为有效的类型时,会导致类型错误。

有关错误的完整定义,请参阅here

因此,很可能上下文或tileData的格式不正确,或者为null或未定义

答案 2 :(得分:0)

这可能是比赛条件。仅在加载图像./images/all_tiles.png时才使用drawImage。但是您正在使用上的图像数据 onload触发。尝试将onload处理程序之后的所有内容移动到onload处理程序中。

答案 3 :(得分:0)

这里的问题是在执行其余脚本之后调用imageObj.onload()函数。

这意味着对getImageData()的查询返回未定义,因为调用时画布中没有图像数据。

解决此问题的一种简单方法是将imageObj.onload函数中的剩余脚本封装起来,如下所示:

$(document).ready(function () {
console.log("Client setup...");
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.tabIndex = 0;
canvas.focus();
console.log("Client focused.");

var imageObj = new Image();
imageObj.src = "./images/all_tiles.png";

imageObj.onload = function() {

  context.drawImage(imageObj, 0, 0);

  var allLoaded = 0;
  var tilesX = imageWidth / tileWidth;
  var tilesY = imageHeight / tileHeight;
  var totalTiles = tilesX * tilesY;        
  var tileData = new Array(); // Array with NO reserved size
  for(var i=0; i<tilesY; i++)
  {
    for(var j=0; j<tilesX; j++)
    {           
      // Store the image data of each tile in the array.
      tileData.push(context.getImageData(j*tileWidth, i*tileHeight, tileWidth, tileHeight));
      allLoaded++;
    }
  }

  context.putImageData(tileData[0], 0 ,0); // Sample paint
}; // End 'imageObj.onload()' scope.

}); // End document ready function scope.

这可确保在getImageData()

之后对context.drawImage()进行任何调用

您可能在此处遇到的问题是您没有绘制图像以覆盖画布。改变这一行:

context.drawImage(imageObj, imageWidth, imageHeight);

context.drawImage(imageObj, 0, 0);

编辑:您还有ImageWidthimageWidth(身高相同)。重命名这些。

编辑:此处使用new Array(totalTiles)保留数组大小导致问题。当我们将新的tile图像推送到数组时,它会推到预分配数组的末尾(从tileData[totalTiles]开始)。通过删除size参数可以很容易地解决这个问题。否则,我们可以将图像数据复制到数组中,而不是使用push(),例如:tileData[n] = getImageData(...),从tileData[0]开始。

答案 4 :(得分:0)

我正在使用Chrome。

context.drawImage(spritesheet.image, 0, 0, 4608, 768);// Works
context.drawImage(spritesheet.image, 768, 0, 768, 768, 4608, 768); // Doesn't work: Uncaught TypeError: Type error

谢谢!