在我的画布项目中,我有两种类型的精灵对象,一种是用矢量图形绘制的,另一种是绘制到画布上的位图图像。
draw function(context){
...
context.lineTo(some place)
context.lineTo(some other place)
etc.
}
另一种类型的精灵是一个位图图像,只要它们是占位符资产,所以它们足够小,不需要onload事件处理程序,但实际资产会更大,所以需要一个。
bitmap loadImage function(){
this.image = new Image();
//Currently my images are too small to warrant an onload eventHandler as they're placeholders
this.image.src = "some path";
}
目前我将所有精灵存储在同一个容器中,并使用简单的循环执行绘图。这现在适用,因为位图精灵没有onload函数。
for each sprite {
sprite.draw(context);
}
一旦我用spritesheets替换占位符资产,他们将需要一个分配给onload事件的函数 - 这会制动我的设计。
任何人都可以了解如何在同一个容器中存储所有精灵并通过遍历该集合来调用绘图吗?
注意:在onload事件处理程序中添加了bitmaps draw,但是(显然)我在加载图像之前在位图sprite上调用draw时会出现错误。
答案 0 :(得分:2)
我制作了这个加载器,允许您将所有图片网址添加到其中,然后调用load()
来启动加载。
您可以使用此类加载程序来支持进度回调,以便您可以向用户显示当前进度。
如果您需要跨原始图像,可以添加一个标志来告诉加载者为图像设置crossOrigin类型,从而添加对此的支持。以下示例为所有图像设置此项,但可以对其进行扩展以支持单个图像。
<强> Live demo here 强>
<强>装载机:强>
/// callback - function to call when finished (mandatory)
/// progress - function to call for each image loaded (optional)
/// progress contains an argument with an "event" containing properties
/// img (the image loaded), url, current (integer) and total (integer)
function imageLoader(callback, progress, error) {
if (typeof callback !== 'function') throw 'Need a function for callback!';
var lst = [],
crossOrigin = false;
this.crossOrigin = function (state) {
if (typeof state !== 'bool') return crossOrigin;
crossOrigin = state;
return this;
}
this.add = function (url) {
lst.push(url);
return this;
}
this.load = function () {
if (lst.length > 0) {
startLoading();
}
return this;
}
function startLoading() {
var i = 0,
url,
count = lst.length,
images = [];
for (; url = lst[i]; i++) {
var img = document.createElement('img');
images.push(img);
img.onload = function () {
_handler(url, this)
};
img.onerror = function (e) {
_handlerError(url, e)
};
if (crossOrigin === true) img.crossOrigin = 'anonymous';
img.src = url;
}
function _handler(url, img) {
count--;
if (typeof progress === 'function') progress({
current: lst.length - count,
total: lst.length,
url: url,
img: img
});
if (count === 0) callback({
images: images,
urls: lst
});
}
function _handlerError(url, e) {
if (typeof error === 'function') error({
url: url,
error: e
});
console.warn('WARNING: Could not load image:', url);
_handler();
}
}
return this;
}
<强>用法:强>
var loader = new imageLoader(done, progress);
/// methods can be chained:
loader.add(url1)
.add(url2)
.add(url3)
.load();
(参见完整示例演示)
然后处理程序可以执行:
function done(e) {
for (i = 0; i < e.images.length; i++) {
/// draw the image
ctx.drawImage(e.images[i], i * 20, i * 20, 40, 40);
}
}
function progress(e) {
///progress bar
status.style.width = ((e.current / e.total) * 100).toFixed(0) + '%';
/// current loaded image
ctx.drawImage(e.img, 0, 340, 60, 60);
}
答案 1 :(得分:0)
http://jsbin.com/IMoFOz/1/edit
请注意,因为它是异步的,所以您需要某种“状态机”或指示资产已完成加载。与桌面游戏的加载“阻止”执行的其余部分不同,您仍然可以在图像加载到后台时执行操作。因此,您可以调用类似start
的函数来绘制图像。
像这样:
function start() {
context.drawImage(image1, 69, 50);
context.drawImage(image2, 150, 150);
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var image1 = new Image();
var image2 = new Image();
var Image = {
count: 0,
Load: function(asset, url) {
asset.src = url;
asset.onload = function() {
Image.count--;
if (Image.count == 0)
{
console.log("Done loading everything.");
start();
}
}
Image.count++;
}
};
Image.Load(image1, 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg');
Image.Load(image2, 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg');