我试图将一堆图像加载到画布上,但是没有出现。源包含指向我要使用的图像的链接。有人有什么想法吗?
这是我第一次使用画布。
<canvas id ="canvas" width = "500" height = "500"></canvas>
<script>
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
loadImages(ctx);
function loadImages()
{
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var number = 0;
var bX = 0;
var bY = 0;
var images = [];
images = getImages();
for(var i = 0;i<images.length;i++){
var t = images[i];
document.write(t.src+"<br>");
ctx.drawImage(t,0,0,100,100);
if(i%4==0)
{
bX = 0;
bY -= 110;
}
else
{
bX+=110;
}
}
}
我做了这个功能来预加载图像并将它们以数组形式返回
function getImages()
{
var imgList = [];
var sources =
[ "http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_00.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_01.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_02.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_03.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_04.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_05.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_06.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_07.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_08.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_09.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_10.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_11.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_12.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_13.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_14.png" ];
var s = 0;
var length = sources.length;
for(s; s< length;++s)
{
imgList[s] = new Image();
imgList[s].src = sources[s];
}
return imgList;
}
</script>
</body>
</html>
答案 0 :(得分:1)
首先,确保正确检索和加载图像。然后将代码调整为以下内容:
for (var i = 1; i <= images.length; i++) {
var t = images[i];
document.write(t.src+"<br>");
ctx.drawImage(t,bX,bY,100,100);
if (i%4 === 0) {
bX = 0;
bY += 110;
}
else {
bX += 110;
}
}
您想要从索引1而不是0进行迭代,这样就不会立即实现if语句i % 4 === 0
。然后,您希望使用变量bX
和bY
作为图像的位置偏移。您使用ctx.drawImage(t,0,0,100,100);
之前将所有图像堆叠在同一位置。最后,增加bY
以便按下图像。
答案 1 :(得分:0)
问题是在尝试绘制图像之前图像没有加载。您应该创建imgs并将它们附加到正文
images = getImages();
for(var i = 0; i<images.length; i++){
var img = document.createElement("img");
img.src= images[i].src;
document.body.appendChild(img);
img.style.display = "none";
img.id="img"+String(i);
}
然后像这样画出它们
loadImages(images);
function loadImages(images){
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
for(var i = 0;i<images.length;i++){
ctx.drawImage(document.getElementById("img"+String(i)),i*10,0,100,100);
if(i%4==0)
{
bX = 0;
bY -= 110;
}
else
{
bX+=110;
}
}
}
我测试了它并且它有效
答案 2 :(得分:0)
除了其他原因之外,它不起作用,因为您在尝试使用它们之前不等待图像加载。您可以使用Image
对象load
event执行此操作。我会写这样的东西,用Promise来管理加载状态。
var images,
nameList = document.getElementById('image-names'), // just a div to display the stuff you were writing out to document. write.
// this function returns a Promise which will resolve once all of the
// images are done loading
preloadImages = function () {
var imagePromises,
sources = [
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_00.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_01.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_02.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_03.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_04.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_05.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_06.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_07.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_08.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_09.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_10.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_11.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_12.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_13.png",
"http://terminus.scu.edu/~ntran/csci168-f15/hw/hw3/tile_14.png"
];
// if we have already loaded and cached the images,
// return them right away wrapped in a resolved Promise
if (images) {
nameList.innerHTML += 'Using cached images.<br>';
return Promise.resolve(images);
}
// otherwise we use .map to iterate over the items in sources and
// create a new array of promises and store them in imagePromises
imagePromises = sources.map(function (src) {
// each of the promises that are created by this function
// are stored in imagePromises and will resolve when the image
// it represents fires its load event
return new Promise(function (resolve, reject) {
var img = new Image();
// once the image has loaded, resolve its Promise
img.onload = function () {
resolve(img);
};
// if there is an error reject this image's Promise
img.onerror = function () {
reject(src + ' failed to load.');
};
img.src = src;
});
});
// Promise.all will create a Promise that will resolve when all of the
// images are loaded (because all of the Promises representing those
// images will have resolved). If there is an error loading any of the
// images it will be rejected, which we can handle later.
return Promise.all(imagePromises)
// after Promise.all returns a resolved Promise, we create a new Promise
// using .then, which is what actually gets returned by preloadImages.
.then(function (loadedImages) {
// cache the loaded images in case we need them later
images = loadedImages;
// return the images so that anything chained off of this Promise
// has access to them.
return loadedImages;
});
},
displayImages = function () {
var c = document.getElementById("canvas"),
ctx = c.getContext("2d"),
bX = 0,
bY = 0;
// preloadImages will return a Promise that will resolve once all of the
// images have been loaded. The .then chained off of that Promise receives
// the list of images via the images parameter
preloadImages().then(function (images) {
var i,
img;
for(i = 0; i < images.length; /* no increment expression, see below */) {
img = images[i];
nameList.innerHTML += img.src + "<br>";
ctx.drawImage(img, bX, bY, 100, 100); // you need to make sure to
// use your offset here
// incrementing here instead of in the increment expression of
// for statement makes this part work correctly
i += 1;
if (i % 4 === 0) {
bX = 0;
bY += 110;
} else {
bX += 110;
}
}
}).catch(function (msg) {
// if there was an error loading any of the images, this .catch
// will display an error
nameList.innerHTML += msg + '<br>';
});
};
displayImages();
有一个working fiddle here。如果您将不存在的图像添加到源列表,您会注意到它显示错误消息而不是绘制到画布。
您不必使用Promises,您可以将preloadImages
作为参数进行回调,然后在加载所有图像后调用它。在这种情况下,您必须手动跟踪已加载的图像数量,并在每个图像的load
事件中检查是否在调用回调之前加载了所有图像。
我的编码风格可能看起来有点奇怪,因为我习惯使用function expressions instead of function statements和其他一些东西,比如严格的等于运算符(===
)。如果您想了解更多关于这种编码风格以及我使用它的原因,我会推荐Douglas Crockford的书 JavaScript:The Good Parts 。 (这是一本很棒的书,即使你不这样做,我也推荐它。)