【发布时间】:2015-08-23 04:23:55
【问题描述】:
我似乎很清楚如何使用 JavaScript 动态加载和绘制图像。我附上一个onload函数并设置图片来源:
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = "your_img_path";
我想对二维图像数组(图块)执行此操作,并多次更新这些图块。但是,如后所述,我在实现这一点时遇到了问题。
我编写的函数(如下所示)包含一些与我当前的问题无关的计算。它们的目的是允许平移/缩放图块(模拟相机)。选择加载的图块取决于请求渲染的位置。
setInterval(redraw, 35);
function redraw()
{
var canvas = document.getElementById("MyCanvas");
var ctx = canvas.getContext("2d");
//Make canvas full screen.
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
//Compute the range of in-game coordinates.
var lowestX = currentX - (window.innerWidth / 2) / zoom;
var highestX = currentX + (window.innerWidth / 2) / zoom;
var lowestY = currentY - (window.innerHeight / 2) / zoom;
var highestY = currentY + (window.innerHeight / 2) / zoom;
//Compute the amount of tiles that can be displayed in each direction.
var imagesX = Math.ceil((highestX - lowestX) / imageSize);
var imagesY = Math.ceil((highestY - lowestY) / imageSize);
//Compute viewport offsets for the grid of tiles.
var offsetX = -(mod(currentX, imageSize) * mapZoom);
var offsetY = -(mod(currentY, imageSize) * mapZoom);
//Create array to store 2D grid of tiles and iterate through.
var imgArray = new Array(imagesY * imagesX);
for (var yIndex = 0; yIndex < imagesY; yIndex++) {
for (var xIndex = 0; xIndex < imagesX; xIndex++) {
//Determine name of image to load.
var iLocX = (lowestX + (offsetX / mapZoom) + (xIndex * imageSize));
var iLocY = (lowestY + (offsetY / mapZoom) + (yIndex * imageSize));
var iNameX = Math.floor(iLocX / imageSize);
var iNameY = Math.floor(iLocY / imageSize);
//Construct image name.
var imageName = "Game/Tiles_" + iNameX + "x" + iNameY + ".png";
//Determine the viewport coordinates of the images.
var viewX = offsetX + (xIndex * imageSize * zoom);
var viewY = offsetY + (yIndex * imageSize * zoom);
//Create Image
imgArray[yIndex * imagesX + xIndex] = new Image();
imgArray[yIndex * imagesX + xIndex].onload = function() {
ctx.drawImage(imgArray[yIndex * imagesX + xIndex], viewX, viewY, imageSize * zoom, imageSize * zoom);
};
imgArray[yIndex * imagesX + xIndex].src = imageName;
}
}
}
如您所见,函数中声明了一个数组,以等于显示的瓷砖网格的大小。数组的元素表面上填充了动态加载后绘制的图像。不幸的是,imgArray[yIndex * imagesX + xIndex] 不被我的浏览器视为图像,我收到错误:
未捕获的类型错误:无法在“CanvasRenderingContext2D”上执行“drawImage”:提供的值不是类型“(HTMLImageElement 或 HTMLVideoElement 或 HTMLCanvasElement 或 ImageBitmap)”
另外,我最初认为数组没有必要。毕竟,如果我只是要在下次调用redraw 时加载一个新图像,为什么我需要在完成绘制后保留图像的句柄?在这种情况下,循环如下所示:
for (var yIndex = 0; yIndex < imagesY; yIndex++) {
for (var xIndex = 0; xIndex < imagesX; xIndex++) {
//Determine name of image to load.
var iLocX = (lowestX + (offsetX / mapZoom) + (xIndex * imageSize));
var iLocY = (lowestY + (offsetY / mapZoom) + (yIndex * imageSize));
var iNameX = Math.floor(iLocX / imageSize);
var iNameY = Math.floor(iLocY / imageSize);
//Construct image name.
var imageName = "Game/Tiles_" + iNameX + "x" + iNameY + ".png";
//Determine the viewport coordinates of the images.
var viewX = offsetX + (xIndex * imageSize * zoom);
var viewY = offsetY + (yIndex * imageSize * zoom);
//Create Image
var img = new Image();
img.onload = function() {
ctx.drawImage(img, viewX, viewY, imageSize * zoom, imageSize * zoom);
};
img.src = imageName;
}
}
自从最后一个处理的图块被渲染后,我对这种方法的运气更好。尽管如此,没有绘制所有其他瓷砖。我想我可能一直在覆盖一些东西,所以只有最后一个保留了它的值。
那么,我该怎么做才能重复渲染 2D 格子网格,从而始终加载瓷砖?
为什么数组元素不被视为图像?
【问题讨论】:
-
imgArray[yIndex * imagesX + xIndex]的类型是什么?尝试将元素记录到控制台。还有为什么是imgArray[xIndex].src = imageName;而不是yIndex * imagesX + xIndex? -
索引不匹配是输入问题时的拼写错误,我会修复它。至于类型,我认为应该是
Image,因为这就是所谓的。我通过控制台记录了图像并打印了<img src="Game/Tiles_1x0.png">
标签: javascript image canvas game-engine