2

我试图打破一个精灵表,它并没有像它应该的那样将它放入一个二维数组中。在我的代码末尾,靠近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/代码的示例小提琴

4

5 回答 5

4

你的问题是第一个元素tileData不是一个ImageData对象,它是一个普通的数字!初始化数组时,您使用:

var tileData = [totalTiles];

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

您可能打算这样做:

var tileData = new Array(totalTiles);

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

于 2012-07-18T15:47:02.413 回答
3

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

有关错误的完整定义,请参见此处

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

于 2012-10-11T19:30:08.903 回答
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)会导致问题。当我们将新的平铺图像推送到数组时,它会推送到预分配数组的末尾(从 开始tileData[totalTiles])。这很容易通过删除 size 参数来解决。push()否则,我们可以在循环中将图像数据复制到数组中,而不是使用,例如: tileData[n] = getImageData(...),从 开始tileData[0]

于 2012-07-18T15:18:11.477 回答
0

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

于 2012-07-18T11:19:43.140 回答
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

谢谢!

于 2013-09-18T09:58:12.653 回答