我正在使用以下代码将一些HTML插入到div中,并预加载该HTML中可能包含的任何图像(html var的数据实际上是从实际代码中的AJAX请求中获取的)。这是为了防止浏览器在显示div(使用slideDown事件)时加载获取的HTML图像 - 因为这会导致效果的流动性在转换中加载图像时被破坏。我想我可以使用隔行扫描的JPEG,这样几乎可以立即知道图像的尺寸,但显然可以找到更清晰的方法。 :P
var html = '<img src="images/test.jpg" alt="test" />';
$('div.content').hide().html(html);
$('div.content img').each(function(){
var img = new Image();
img.src = $(this).attr('src');
$(this).attr('src', img.src);
});
$('div.content').slideDown('normal');
我正在使用Image对象及其后续分配,根据给出here的建议,但不幸的是,浏览器使用此方法仍未缓存图像,因为sildeDown()效果仍然被中断当图像加载时。
任何帮助或替代方法?非常感谢。
进展!原来浏览器是缓存图像,我只是没有给它时间这样做(它只需要一秒加载alert()或setInterval())。现在介绍可能是最混乱的代码 - 我使用无限循环来创建暂停。
新方法通过将函数(将每个图像的src添加到数组)绑定到该图像的成功加载事件来扩展上面的旧代码。然后它会在等待所有图像加载并因此出现在数组中时陷入无限循环。这似乎可以作为同步预加载图像的一种方式 - 但问题仍然存在;某些原因的while()循环甚至在所有图像都被加载后无限循环,除非我添加一个alert()来暂停它。
新代码:
var html = '<img src="images/test.jpg" alt="test" />';
$('div.content').hide().html(html);
// define usr variables object
$.usrvar = {};
// array of loaded images' urls
$.usrvar.images = [];
// boolean for whether this content has images (and if we should check they are all loaded later)
$.usrvar.hasimages = false;
// foreach of any images inside the content
$('div.content img').each(function(){
// if we're here then this content has images..
$.usrvar.hasimages = true;
// set this image's src to a var
var src = $(this).attr('src');
// add this image to our images array once it has finished loading
$(this).load(function(){
$.usrvar.images.push(src);
});
// create a new image
var img = new Image();
// set our new image's src
img.src = src;
});
// avoid this code if we don't have images in the content
if ($.usrvar.hasimages != false) {
// no images are yet loaded
$.usrvar.imagesloaded = false;
// repeatedly cycle (while() loop) through all images in content (each() loop)
while ($.usrvar.imagesloaded != true) {
$('div.content img').each(function(){
// get this loop's image src
var src = $(this).attr('src');
// if this src is in our images array, it must have finished loading
if ($.usrvar.images.indexOf(src) != -1) {
// set imagesloaded to trueai
$.usrvar.imagesloaded = true;
} else {
// without the pause caused by this alert(), this loop becomes infinite?!
alert('pause');
// this image is not yet loaded, so set var to false to initiate another loop
// (ignores whether imagesloaded has been set to true by another image, because ALL
// need to be loaded
$.usrvar.imagesloaded = false;
}
});
}
}
$('div.content').slideDown('normal');
答案 0 :(得分:1)
我做了以下解决方案,但尚未经过测试,因此您已收到警告;)
// HTML (any formatting possible)
// no src for the images: it is provided in alt which is of the form url::actualAlt
var html = "<p><img alt='images/test.jpg::test' /><br />Some Text<br /><img alt='images/test2.jpg::test2' /></p>";
$(document).ready(function() {
// Reference to the content div (faster)
var divContent = $("div.content");
// Hide the div, put the HTML
divContent.hide().html(html);
// Webkit browsers sometimes do not parse immediately
// The setTimeout(function,1) gives them time to do so
setTimeout(function() {
// Get the images
var images = $("img",divContent);
// Find the number of images for synchronization purpose
var counter = images.length;
// Synchronizer
// will show the div when all images have been loaded
function imageLoaded() {
if (--counter<=0) $('div.content').slideDown('normal');
}
// Loading loop
// For each image in divContent
$.each(images,function() {
// Get the url & alt info from the alt attribute
var tmp = $(this).attr("alt").split("::");
// Set the alt attribute to its actual value
$(this).attr("alt",tmp[1]);
// Wire the onload & onerror handlers
this.onload = this.onerror = imageLoaded;
// Set the image src
this.src = tmp[0];
});
},1);
});
答案 1 :(得分:0)
创建一个间隔/超时并让它检查你的compterGenerated css-height,如果它是自动调整的,它将从0开始并结束到100(例如)。但是在Safari中,它会在图像之前加载高度,因此它可能无法在所有浏览器中运行...
答案 2 :(得分:0)
我正在玩这个,我创建了一个稍微不同的解决方案。不是在加载数据时将图像推送到数组上,而是将它们全部推送到循环中的数组上,然后在加载事件中将它们从数组中删除并调用“完成”函数。它检查图像数组是否为空,如果是,则清除并显示内容。
var html = '< animg src="images/test.jpg" alt="test" />'; // not allowed to post images...
$('div.content').hide().html(html);
// preload images
// define usr variables object
$.usrvar = {};
// array of loaded images' urls
$.usrvar.images = [];
// initially no images
$.usrvar.hasimages = false;
$('div.content img').each(function() {
// if we're here then this content has images..
$.usrvar.hasimages = true;
// set this image's src to a var
var src = this.src;
// add this image to our images array
$.usrvar.images.push(src);
// callback when image has finished loading
$(this).load(function(){
var index = $.usrvar.images.indexOf(src);
$.usrvar.images.splice(index,1);
finish_loading();
});
// create a new image
var img = new Image();
// set our new image's src
img.src = src;
});
if(!$.usrvar.hasimages) finish_loading();
function finish_loading() {
if($.usrvar.hasimages) {
if($.usrvar.images.length > 0) return;
}
$('div.content').slideDown('normal');
}
编辑:看看朱利安的帖子,他的方法更好。我的方法以类似的方式工作,但是像原始解决方案一样通过一系列srcs跟踪图像而不仅仅是一个计数(这更有效)。
编辑2:我认为这是一个更好的解决方案,但它似乎对我不起作用。也许与负载事件被调用太接近彼此有关。有时它会工作,但有时它会在加载图像时挂起,图像计数器永远不会达到零。我已经回到上面帖子中的方法了。
编辑3:看起来是造成问题的setTimeout。
答案 3 :(得分:0)
这就是我使用的。正如你从我的观点中看到的那样,我不是专业人士,但我发现它在某个地方并且它对我来说很有用,并且看起来比发布的所有内容都简单得多。也许我错过了一个要求。 :)
var myImgs = ['images/nav/img1.png', 'images/nav/img2.png', 'images/nav/img3.png', 'images/nav/img4.png', 'images/expand.png', 'images/collapse.png'];
function preload(imgs) {
var img;
for (var i = 0, len = imgs.length; i < len; ++i) {
img = new Image();
img.src = imgs[i];
}
}
preload(myImgs);