我正在编写一个脚本,用户在其中选择一系列数据,然后从服务器获取一堆图像(超过150个),然后我通过它们循环制作类似电影的内容。我想知道的是在移动图像时加载防止滞后的最有效方法。
目前,我正在使用Ajax从服务器获取图像,并将它们存储在JavaScript上的Image对象数组中。在HTML中我有一个div标签,我希望在其中放置图像。在我完成了在数组中创建所有Image对象(并设置其正确的src)之后,我执行以下操作:
imgElem = document.createElement('img');
document.getElementById('loopLocation').appendChild(imgElem);
imgElem.src = images[0].src;
在此之后,我只是进行最后一次调用,但更改了循环索引。我每400毫秒做一次。循环工作,但有时它滞后,它在图像上冻结的时间应该更长。我想知道我是否能够从客户端改进这一点,或者我只需要一台响应速度更快的服务器。
答案 0 :(得分:6)
您可能需要考虑spriting将所有图像放入一个大图像中。有了这个,你只需要加载一个大图像,然后只需重新定位每个场景。
或者,您可能还想在实际使用它们之前预先加载这150个图像。你可以使用JS数组来存储Image对象,然后遍历那个数组来获取你的图像。
var images = [];
var expectLoaded = 150;
for(var i = 0; i<expectLoaded;i++){
(function(i){
//new image object
var img = new Image();
//onload hander
img.onload = function(){
//after load, push it into the array
images.push[img];
//and check if the all has loaded
if(images.length === expectLoaded){
//preload done
}
}
//start loading this image
img.src = //path to image[i];
},(i));
}
循环阻止UI线程。 JS是单线程的,意味着代码以线性方式一个接一个地执行。在循环语句之后出现的任何内容都将等到循环结束。如果那个循环需要很长时间......抓一些咖啡。此外,由于您正在操作DOM,因此您不会看到自UI线程被阻止后的更改。
但有一些方法可以绕过这个,其中一个方法是使用超时来延迟和排队代码,以便以后执行,当JS不忙时。
function animate(frameNo){
//animate frame[frameNo];
if(frameNo < total_frames){ //make the UI breate in between frames
setTimeout(function(){ //so that changes reflect on the screen
animate(++frameNo); //then animate next frame
},200);
}
}
//start
animate(0);
答案 1 :(得分:2)
我同意约瑟夫的第二点。这是在开始循环之前完成图像预加载的一个很好的链接:http://www.javascriptkit.com/javatutors/preloadimagesplus.shtml