JavaScript 图片仅在刷新时加载
JavaScript Image only loads on refresh
我目前正在努力解决我的游戏引擎中一个非常烦人的问题...
我无法弄清楚为什么第一次加载页面时图像没有加载,为了使这项工作我必须刷新它。
这是我当前的代码:
纹理创建:
/**
* @param {GLContext} context Context
* @param {boolean} clamp Clamp
* @param {Integer} filter Filter
*/
this.create = function(filename, context, filter, clamp) {
this.filename = filename;
this.context = context;
var gl = context.GL;
this.id = gl.createTexture();
this.id.image = new Image();
var _this = this;
this.id.image.onload = function() {
gl.bindTexture(gl.TEXTURE_2D, _this.id);
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
if (clamp) {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
} else {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
}
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this);
gl.bindTexture(gl.TEXTURE_2D, null);
loaded = true;
};
this.id.image.src = filename;
// ...
};
资源加载:
/**
* Load all texture resources
*/
this.loadTextureResources = function() {
for (var key in queue) {
var i = queue[key];
var tmpt = new Texture();
tmpt.create(i.filename, context, i.filter, i.clamp);
this.resources[key] = tmpt;
}
};
和游戏初始化:
/**
* Start game
*/
this.start = function() {
this.loadTextureResources();
tree.create();
if (typeof this.oncreate === "function") this.oncreate();
setTimeout(this.gameloop, 500);
};
(我几乎尽我所能,并花了 3 天时间试图解决这个问题...)
提前致谢...
在所有现代网络浏览器中,图像都是异步加载的,以提高速度。因此,只有在页面刷新后,您的图像才会加载得足够早,因为它们已经被缓存了。
首先尝试缓存您的图像,只有在它们被缓存后,才触发其余的逻辑。
图片缓存到浏览器后,下次使用时加载速度会更快。
要缓存图像,您所要做的就是将它们加载到浏览器中。
您可以像这样缓存图像:
function cacheImages(array)
{
if (!cacheImages.list) {
cacheImages.list = [];
}
var list = cacheImages.list;
for (var i = 0; i < array.length; i++) {
var img = new Image();
img.onload = function() {
var index = list.indexOf(this);
if (index !== -1) {
// remove image from the array once it's loaded
// for memory consumption reasons
list.splice(index, 1);
}
}
list.push(img);
img.src = array[i];
}
}
cacheImages(["url1.jpg", "url2.jpg", "url3.jpg"]);
最终,随着时间的推移,浏览器缓存可能会填满并删除未使用的最旧内容。
因此,建议您始终尝试缓存,因为如果浏览器已经有图像,则不会再次保存它(如果浏览器足够聪明,通常不会保存重复的图像)。
图像加载是异步的。例如,如果需要几秒钟,图像的 'onload' 只会在几秒钟后被调用,而当前作用域中的代码会继续执行。您的示例似乎无法解决这个问题。当然,我没有仔细阅读您的示例链接的全部内容,所以我可能会弄错。
您可能最好让某个资产管理器为您处理此问题,并将整个绘图初始化包装在一个回调中,该回调仅在所有需要的资源加载完成后调用。
第二次这不是问题的原因是图像来自缓存,并且大多数浏览器(我认为 IE 是例外)一旦附加到资源就直接调用 onload 处理程序已加载。
顺便说一句,如果你有这样的问题,在服务器端重写一些缓冲脚本,故意延迟响应,这样你可以更好地看到效果。它对调试有很大帮助,例如一个简单的 PHP 脚本执行 sleep(3);
,然后传递文件。当然,也可以使用浏览器的节流功能。
我目前正在努力解决我的游戏引擎中一个非常烦人的问题... 我无法弄清楚为什么第一次加载页面时图像没有加载,为了使这项工作我必须刷新它。 这是我当前的代码:
纹理创建:
/**
* @param {GLContext} context Context
* @param {boolean} clamp Clamp
* @param {Integer} filter Filter
*/
this.create = function(filename, context, filter, clamp) {
this.filename = filename;
this.context = context;
var gl = context.GL;
this.id = gl.createTexture();
this.id.image = new Image();
var _this = this;
this.id.image.onload = function() {
gl.bindTexture(gl.TEXTURE_2D, _this.id);
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
if (clamp) {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
} else {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
}
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this);
gl.bindTexture(gl.TEXTURE_2D, null);
loaded = true;
};
this.id.image.src = filename;
// ...
};
资源加载:
/**
* Load all texture resources
*/
this.loadTextureResources = function() {
for (var key in queue) {
var i = queue[key];
var tmpt = new Texture();
tmpt.create(i.filename, context, i.filter, i.clamp);
this.resources[key] = tmpt;
}
};
和游戏初始化:
/**
* Start game
*/
this.start = function() {
this.loadTextureResources();
tree.create();
if (typeof this.oncreate === "function") this.oncreate();
setTimeout(this.gameloop, 500);
};
(我几乎尽我所能,并花了 3 天时间试图解决这个问题...)
提前致谢...
在所有现代网络浏览器中,图像都是异步加载的,以提高速度。因此,只有在页面刷新后,您的图像才会加载得足够早,因为它们已经被缓存了。
首先尝试缓存您的图像,只有在它们被缓存后,才触发其余的逻辑。
图片缓存到浏览器后,下次使用时加载速度会更快。
要缓存图像,您所要做的就是将它们加载到浏览器中。
您可以像这样缓存图像:
function cacheImages(array)
{
if (!cacheImages.list) {
cacheImages.list = [];
}
var list = cacheImages.list;
for (var i = 0; i < array.length; i++) {
var img = new Image();
img.onload = function() {
var index = list.indexOf(this);
if (index !== -1) {
// remove image from the array once it's loaded
// for memory consumption reasons
list.splice(index, 1);
}
}
list.push(img);
img.src = array[i];
}
}
cacheImages(["url1.jpg", "url2.jpg", "url3.jpg"]);
最终,随着时间的推移,浏览器缓存可能会填满并删除未使用的最旧内容。
因此,建议您始终尝试缓存,因为如果浏览器已经有图像,则不会再次保存它(如果浏览器足够聪明,通常不会保存重复的图像)。
图像加载是异步的。例如,如果需要几秒钟,图像的 'onload' 只会在几秒钟后被调用,而当前作用域中的代码会继续执行。您的示例似乎无法解决这个问题。当然,我没有仔细阅读您的示例链接的全部内容,所以我可能会弄错。
您可能最好让某个资产管理器为您处理此问题,并将整个绘图初始化包装在一个回调中,该回调仅在所有需要的资源加载完成后调用。
第二次这不是问题的原因是图像来自缓存,并且大多数浏览器(我认为 IE 是例外)一旦附加到资源就直接调用 onload 处理程序已加载。
顺便说一句,如果你有这样的问题,在服务器端重写一些缓冲脚本,故意延迟响应,这样你可以更好地看到效果。它对调试有很大帮助,例如一个简单的 PHP 脚本执行 sleep(3);
,然后传递文件。当然,也可以使用浏览器的节流功能。