我试图逐帧加载jpeg图像,以创建jpeg图像的序列动画。我正在尝试使用javascript在递归循环中加载它们。 我需要线性加载图像以实现动画的渐进式回放。 (在加载所有帧之前开始播放)由于函数的自然递归,我从IE得到Stack overflow at line: 0
错误。 (我的真实代码加载超过60帧)
以下是我如何执行此操作的基本示例:
var paths = ['image1.jpg', 'image2.jpg', 'image3.jpg']; //real code has 60+ frames
var images = [];
var load_index = 0;
var load = function(){
var img = new Image();
img.onload = function(){
if(load_index<=paths.length){
load_index++;
load();
}else{
alert('done loading');
}
}
img.src = paths[load_index];
images.push(img);
}
在调用加载的下一步时,似乎可以通过使用间隔为1的setTimeout来避免此错误。这似乎让IE在加载下一张图像之前“呼吸”,但降低了图像加载速度。
任何人都知道如何避免这种堆栈溢出错误?
http://cappuccino.org/discuss/2010/03/01/internet-explorer-global-variables-and-stack-overflows/
上面的链接建议将函数包装起来将其从window对象中删除将有助于避免堆栈溢出错误。但是我看到奇怪的是它只通过序列得到大约15帧然后就死了。
答案 0 :(得分:0)
简单地说,在这种情况下不要使用递归函数,没有任何需要:
var paths = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
var images = [];
var loads = [];
/// all complete function, probably should be renamed to something with a
/// unique namespace unless you are working within your own function scope.
var done = function(){
alert('all loaded');
}
var loaded = function(e,t){
/// fallbacks for old IE
e = e||Event; t = e.target||e.srcElement;
/// keep a list of the loaded images, you can delete this later if wanted
loads.push( t.src );
if ( loads.length >= paths.length ) {
done();
}
}
var load = function(){
var i, l = paths.length, img;
for( i=0; i<l; i++ ){
images.push(img = new Image());
img.onload = loaded;
img.src = paths[i];
}
}
事实上,正如您所发现的那样,您目前使用的方法非常密集。相反,上述版本不会为每个onload
侦听器(节省内存)创建新函数,并将触发与浏览器允许的一样多的并发加载(而不是等待每个图像加载)。
(上述内容已经手动输入,尚未经过测试)
啊,那么为什么你这样做会更有意义:)在那种情况下,你使用setTimeout
的第一种方法可能是最好的解决方案(你应该可以使用超时) 0
)。如果可以避免这种情况,仍然有重新安排事情的空间。以下可能会解决问题...
var paths = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
var images = []; /// will contain the image objects
var loads = []; /// will contain loaded paths
var buffer = []; /// temporary buffer
var done = function(){ alert('all loaded'); }
var loaded = function(e,t){
e = e||Event; t = e.target||e.srcElement; loads.push( t.src );
/// you can do your "timing/start animation" calculation here...
/// check to see if we are complete
if ( loads.length >= paths.length ) { done(); }
/// if not fire off the next image load
else { next(); }
}
var next = function(){
/// current will be the next image
var current = buffer.shift();
/// set the load going for the current image
if ( current ) { current.img.src = current.path; }
}
var load = function(){
var i, l = paths.length, img;
for( i=0; i<l; i++ ){
img = new Image();
img.onload = loaded;
/// build up a list of images and paths to load
buffer.push({ img: img, path: paths[i] });
}
/// set everything going
next();
}
如果上面没有这样做,另一种解决问题的方法是逐步浏览路径列表,并附加一串图像标记(可以在屏幕外渲染)使用它自己的onload="next()"
处理程序... next()
将负责插入下一个图像。通过执行此操作,它可以将负载触发和后续加载事件切换到代码外部,并且可以绕过堆叠调用。