我在这里(http://nettuts.com ...)看到了:
function complexLoad(config, fileNames) {
for (var x = 0; x < fileNames.length; x++) {
$("<img>").attr({
id: fileNames[x],
src: config.imgDir + fileNames[x] + config.imgFormat,
title: "The " + fileNames[x] + " nebula"
}).appendTo("#" + config.imgContainer).css({ display: "none" });
}
};
但是,对于我想要的东西来说似乎有点过高了!
我知道那里有jQuery插件可以做到这一点,但是它们看上去都很大(大小);我只需要一种快速,轻松和简短的方式来预加载图像!
#1 楼
快速简便:function preload(arrayOfImages) {
$(arrayOfImages).each(function(){
$('<img/>')[0].src = this;
// Alternatively you could use:
// (new Image()).src = this;
});
}
// Usage:
preload([
'img/imageName.jpg',
'img/anotherOne.jpg',
'img/blahblahblah.jpg'
]);
或者,如果您想要jQuery插件:
$.fn.preload = function() {
this.each(function(){
$('<img/>')[0].src = this;
});
}
// Usage:
$(['img1.jpg','img2.jpg','img3.jpg']).preload();
评论
不需要将图像元素插入DOM来确保浏览器对其进行缓存吗?
– JoshNaro
2010年8月17日15:33
我相信$('')只会在内存中创建一个图像元素(请参阅链接)。看起来'$('')实际上会在隐藏的DIV中创建元素,因为它更加“复杂”。但是,我认为大多数浏览器都不需要这样做。
– JoshNaro
2011年2月11日15:30
那是编写jQuery插件的怪异方式。为什么不$ .preload(['img1.jpg','img2.jpg'])?
– alex
2012年1月17日在2:56
确保在$(window).load(function(){/ * preload here * /})内调用此函数;因为这样可以首先加载文档中的所有图像,所以可能首先需要使用它们。
–贾斯珀·肯尼斯(Jasper Kennis)
2012年5月5日15:35
@RegionalC-为防止在设置加载事件之前完成加载图像,在设置src之前设置加载事件可能会更安全一些? $('')。load(function(){/ *已加载!* /})。attr('src',this);
–备用字节
13年2月4日在22:01
#2 楼
这是第一个响应的经过调整的版本,该响应实际上将图像加载到DOM中并默认隐藏它。function preload(arrayOfImages) {
$(arrayOfImages).each(function () {
$('<img />').attr('src',this).appendTo('body').css('display','none');
});
}
评论
hide()比css('display','none')更简洁。
– alex
2011-09-22 2:32
将它们插入DOM有什么好处?
– alex
13年5月7日在21:56
我也想知道将它们插入DOM的好处。
– jedmao
13年7月3日在23:39
根据我的经验,将图像预加载到DOM中会使浏览器意识到其存在并对其进行适当的缓存。否则,该图像仅存在于内存中,该内存仅适用于单页应用程序。
–丹尼斯·朗戈(Dennis Rongo)
13年7月4日在18:00
丹尼斯·朗戈。将图片添加到DOM可以解决Chrome上随机重新加载的问题。谢谢!
– tmorell
13年7月7日在2:53
#3 楼
使用JavaScript图像对象。此功能允许您在加载所有图片时触发回调。但是,请注意,如果未加载至少一个资源,它将永远不会触发回调。可以通过实现
onerror
回调并增加loaded
值或处理错误来轻松解决此问题。var preloadPictures = function(pictureUrls, callback) {
var i,
j,
loaded = 0;
for (i = 0, j = pictureUrls.length; i < j; i++) {
(function (img, src) {
img.onload = function () {
if (++loaded == pictureUrls.length && callback) {
callback();
}
};
// Use the following callback methods to debug
// in case of an unexpected behavior.
img.onerror = function () {};
img.onabort = function () {};
img.src = src;
} (new Image(), pictureUrls[i]));
}
};
preloadPictures(['http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar'], function(){
console.log('a');
});
preloadPictures(['http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar'], function(){
console.log('b');
});
评论
做正确的事,使用JavaScript Image对象。您在这些答案中发现有人做错事了吗?
– alex
13年5月7日在21:58
出色的代码。我是否认为即使缓存了图像也会触发onload事件,这是正确的吗? (因为首先声明了img.onload)。这是我的测试所显示的。
– Startec
2014年5月23日上午10:06
@alex可能,是的。如果目标是预加载(表示性能顺序),那么我希望看到一个原始的JS选项,而不是jQuery依赖的选项。
– Charlie Schliesser
14年7月15日在23:57
我喜欢这个解决方案,但是我发现它不能在Firefox中使用。是我还是其他人有同样的问题?
–万亿
2014年8月20日19:37
@Gazillion提供更多详细信息。您如何定义“无效”?什么是FF版本?
–加雷斯
14年8月20日在20:30
#4 楼
JP,检查完您的解决方案后,我在Firefox中仍然遇到问题,即在继续加载页面之前无法预加载图像。我通过在服务器端脚本中添加一些sleep(5)
来发现此问题。我根据您的情况实施了以下解决方案,似乎可以解决此问题。基本上,我向您的jQuery preload插件添加了一个回调,以便在正确加载所有图像后调用它。
// Helper function, used below.
// Usage: ['img1.jpg','img2.jpg'].remove('img1.jpg');
Array.prototype.remove = function(element) {
for (var i = 0; i < this.length; i++) {
if (this[i] == element) { this.splice(i,1); }
}
};
// Usage: $(['img1.jpg','img2.jpg']).preloadImages(function(){ ... });
// Callback function gets called after all images are preloaded
$.fn.preloadImages = function(callback) {
checklist = this.toArray();
this.each(function() {
$('<img>').attr({ src: this }).load(function() {
checklist.remove($(this).attr('src'));
if (checklist.length == 0) { callback(); }
});
});
};
出于兴趣,我在此使用的方法如下:
(像我一样)从Google来到此页面的人,他们正在寻找一种在Ajax调用中预加载图像的解决方案。
评论
对于那些不希望弄乱Array.prototype的人,可以执行以下操作:checklist = this.length在onload函数中:checklist--然后:if(checklist == 0)callback();
– MiniGod
2012年7月15日在0:35
一切都很好,但是向您不拥有的对象添加新方法或删除现有方法是JavaScript中最差的做法之一。
– Rihards
2012-09-10 7:17
不错,快捷,但是如果其中一张图片损坏或无法加载,则此代码将永远不会触发回调。
– SammyK
2012年10月30日在6:38
.attr({src:this})。load(function(){...})应该是.load(function(){...})。attr({src:this})否则您将遇到缓存问题。
–凯文B
13年3月27日在14:31
#5 楼
这段jQuery代码创建(并加载)了一个DOM元素img而没有显示它:$('<img src="img/1.jpg"/>');
评论
@huzzah-您最好只使用精灵。更少的http请求。 :)
– Alex K
2012年11月16日16:28
#6 楼
$.fn.preload = function (callback) {
var length = this.length;
var iterator = 0;
return this.each(function () {
var self = this;
var tmp = new Image();
if (callback) tmp.onload = function () {
callback.call(self, 100 * ++iterator / length, iterator === length);
};
tmp.src = this.src;
});
};
用法非常简单:
$('img').preload(function(perc, done) {
console.log(this, perc, done);
});
http://jsfiddle.net/yckart/ACbTK/
评论
这是一个非常好的答案,它确实应该是恕我直言的最高投票答案。
–sleepycal
14年1月24日在16:08
一些解释性的话会很好。
– Robsch
17年1月2日在8:12
好的答案,但我建议使用picsum.photos而不是lorempixel.com
– Aleksandar
19年12月26日在16:00
#7 楼
我有一个小插件可以处理这个问题。它叫做waitForImages,它可以处理
img
元素或任何引用CSS中图像的元素,例如div { background: url(img.png) }
。如果您只想加载所有图像,包括CSS中引用的图像,这是您的操作方法:)
$('body').waitForImages({
waitForAll: true,
finished: function() {
// All images have loaded.
}
});
评论
这个插件会导致尚未出现在页面上的图像被加载,还是仅将事件附加到已经要加载的图像上?
–戴夫·卡梅伦(Dave Cameron)
2012年5月29日19:11
@DaveCameron它不考虑图像是否可见。您可以轻松地进行分叉并进行更改-只需将:visible添加到自定义选择器即可。
– alex
2012年5月29日23:44
这个插件看起来非常有趣。但是,jquery文档强调了将加载事件应用于图像时:“无法始终如一地或可靠地跨浏览器工作”。插件如何解决这个问题?
– EleventyOne
13年10月28日在1:11
@EleventyOne检查有关自定义选择器的源。
– alex
13-10-28在2:18
@alex这个插件如何加载元素:hover上css中设置的图像?它对我不起作用
–菲利普·霍夫曼(Philipp Hofmann)
2014年3月27日在9:14
#8 楼
您可以使用cssdisplay:none;
规则在html的某处加载图片,然后在需要使用js或jquery时显示它们不要使用js或jquery函数进行预加载只是css规则要执行的js
示例:HTML
<img src="someimg.png" class="hide" alt=""/>
css:
.hide{
display:none;
}
jQuery:
//if want to show img
$('.hide').show();
//if want to hide
$('.hide').hide();
用jquery / javascript预加载图像效果不好,因为图像在页面中加载需要几毫秒,而您还要花费几毫秒来解析和执行脚本,尤其是如果它们是大图像,那么将它们隐藏在hml中也对性能有更好的影响,因为图像实际上是预加载的,根本看不到蜂鸣声,直到显示出来为止!
评论
有关此方法的更多信息,请参见:perishablepress.com/…
– gdelfino
2012年4月30日0:00在
但是,您需要意识到这种技术的主要缺点:在加载所有图像之前,不会完全加载页面。根据要预加载的图像数量及其大小,这可能需要一些时间。更糟糕的是,如果标记未指定高度和宽度,则某些浏览器可能会等到获取图像后再呈现页面的其余部分。
–user246645
13年2月1日在9:18
@Alex无论如何都需要加载img,您可以自由选择是否使用html加载它们,并避免任何形式的闪烁和一半加载的图像,或者如果您想获得更快的速度来获得一个不稳定的解决方案
–itsme
13年2月1日在9:46
我也真的认为用javascript创建html标签根本不可读,仅我的2美分
–itsme
13年2月1日在9:47
我需要一个非常复杂的项目的快速解决方案,就是这样。
–暴风雨
13年5月27日在8:14
#9 楼
这个jquery imageLoader插件仅1.39kb。用法:
$({}).imageLoader({
images: [src1,src2,src3...],
allcomplete:function(e,ui){
//images are ready here
//your code - site.fadeIn() or something like that
}
});
还有其他选项,例如是否要同步加载图像或每个图像的同步和异步事件。
评论
@AamirAfridi为什么?
–伊恩
13年5月5日在19:31
@Ian,因为在触发回调时文档已经准备就绪。 $(document).ready用于确保已加载DOM。当涉及到回调时,这意味着所有图像都已加载,这意味着已加载yoru DOM,因此在回调内部无需document.ready。
– Aamir Afridi
13年3月6日在15:09
@AamirAfridi无法保证文档已在回调中准备好……您从何处推断出该信息?插件页面上没有任何内容表明DOM准备就绪后将执行allcomplete回调。 DOM准备就绪后,图像很有可能完成加载,但没有理由假设。我不知道您为什么认为回调是神奇的,并且在DOM准备就绪后执行回调...您能解释一下从哪里获得回调吗?仅仅因为图像已加载并不意味着DOM已准备就绪
–伊恩
2013年3月6日15:47
@AamirAfridi插件的文档甚至说:注意,要将其用作图像预加载器,只需将$(document).ready(function(){});放进去。进入您的“ allcomplete”事件:>简单! ...直接推荐此答案显示的内容。
–伊恩
13年6月6日在15:49
@AamirAfridi对于这种情况,这没有任何意义。该插件是一个预加载器。您想尽快执行它。并且有很多事情与您希望尽快启动的DOM不相关,然后在DOM准备就绪时执行一些操作。
–伊恩
2013年3月6日20:27
#10 楼
快速,无插件的预加载jQuery中图像并获得回调函数的方法是一次创建多个img
标签并计算响应,例如,function preload(files, cb) {
var len = files.length;
$(files.map(function(f) {
return '<img src="'+f+'" />';
}).join('')).load(function () {
if(--len===0) {
cb();
}
});
}
preload(["one.jpg", "two.png", "three.png"], function() {
/* Code here is called once all files are loaded. */
});
请注意,如果要支持IE7,则需要使用这个不太漂亮的版本(在其他浏览器中也可以使用):
function preload(files, cb) {
var len = files.length;
$($.map(files, function(f) {
return '<img src="'+f+'" />';
}).join('')).load(function () {
if(--len===0) {
cb();
}
});
}
#11 楼
谢谢你!我想在JP的答案上加上一点即兴之处-我不知道这对任何人都没有帮助,但是这样一来,您不必创建图像阵列,就可以预加载所有大图像如果您的拇指正确命名。这很方便,因为我有一个用html编写所有页面的人,它确保了他们要做的少一步-消除了创建图像数组的需要,而另一步可能使事情搞砸了。$("img").each(function(){
var imgsrc = $(this).attr('src');
if(imgsrc.match('_th.jpg') || imgsrc.match('_home.jpg')){
imgsrc = thumbToLarge(imgsrc);
(new Image()).src = imgsrc;
}
});
基本上,页面上的每个图像都会抓取每个图像的src,如果它符合特定条件(是拇指或首页图像),它将更改名称(在图像src中使用基本字符串替换),然后加载图像。在我的情况下,页面上到处都是拇指图像,都命名为image_th.jpg之类的东西,所有对应的大图像都命名为image_lg。 jpg。大拇指只需将_th.jpg替换为_lg.jpg,然后预加载所有大图像。
希望对您有所帮助。
#12 楼
jQuery.preloadImage=function(src,onSuccess,onError)
{
var img = new Image()
img.src=src;
var error=false;
img.onerror=function(){
error=true;
if(onError)onError.call(img);
}
if(error==false)
setTimeout(function(){
if(img.height>0&&img.width>0){
if(onSuccess)onSuccess.call(img);
return img;
} else {
setTimeout(arguments.callee,5);
}
},0);
return img;
}
jQuery.preloadImages=function(arrayOfImages){
jQuery.each(arrayOfImages,function(){
jQuery.preloadImage(this);
})
}
// example
jQuery.preloadImage(
'img/someimage.jpg',
function(){
/*complete
this.width!=0 == true
*/
},
function(){
/*error*/
}
)
评论
欢迎使用Stack Overflow!而不是仅发布一段代码,请解释为什么此代码解决了所提出的问题。没有解释,这不是答案。
–马丁·彼得斯(Martijn Pieters)♦
2012年11月19日14:41
#13 楼
我使用以下代码:$("#myImage").attr("src","img/spinner.gif");
var img = new Image();
$(img).load(function() {
$("#myImage").attr("src",img.src);
});
img.src = "http://example.com/imageToPreload.jpg";
评论
首先绑定到load事件,然后设置src。
–凯文B
13年3月27日在14:25
#14 楼
我将使用清单文件来告诉(现代)网络浏览器以加载所有相关图像并将其缓存。使用Grunt和grunt-manifest自动执行此操作,而无需再担心预加载脚本,缓存无效器,CDN等。https://github.com/gunta/grunt-manifest
#15 楼
即使在IE9中,这也对我有效:$('<img src="' + imgURL + '"/>').on('load', function(){ doOnLoadStuff(); });
评论
这最终将由于缓存而失败,请始终在设置src属性之前绑定load事件。
–凯文B
2013年3月27日14:27
#16 楼
我想通过Google Maps API自定义叠加层实现此目的。他们的示例代码仅使用JS插入IMG元素,并显示图像占位符框,直到加载图像为止。我在这里找到了一个对我有用的答案:https://stackoverflow.com/a/10863680/2095698。$('<img src="'+ imgPaht +'">').load(function() {
$(this).width(some).height(some).appendTo('#some_target');
});
这会像以前建议的那样预加载图像,并且然后在加载img URL后使用处理程序附加img对象。 jQuery的文档警告说,缓存的图像无法与此事件/处理程序代码一起很好地工作,但是它在FireFox和Chrome中对我有效,并且我不必担心IE。
评论
如您所知,这不适用于缓存的图像。解决方法是先绑定load事件,然后设置src属性。
–凯文B
2013年3月27日14:24在
#17 楼
function preload(imgs) {
$(imgs).each(function(index, value) {
$('<img />').attr('src', value).appendTo('body').css('display', 'none');
});
}
.attr('src',value)
不是
.attr('src',this)
指出来:)
评论
将此范围限定在传递给$ .each的回调中,并分配给要迭代的值。
–奥贝克
13年7月28日在8:13
? $(['img1.jpg','img2.jpg','img3.jpg'])。each(function(index,value){console.log(value); // img1.jpg console.log(this) ; // String {0 =“ i”,1 =“ m”,2 =“ g”,更多...} $('')。attr('src',this).appendTo(' body')。css('display','none');});
– Whisher
13年7月29日在12:32
嗯我想你就在这里。例如$(“ div”)。each(function(i,el){console.log(el == this);});产生所有真理;数组迭代似乎表现出不同的行为。
–奥贝克
13年7月30日在18:59
#18 楼
我通常在我的项目中使用此代码段来加载页面中的图像。您可以在这里查看结果https://jsfiddle.net/ftor34ey/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<img src="https://live.staticflickr.com/65535/50020763321_d61d49e505_k_d.jpg" width="100" />
<img src="https://live.staticflickr.com/65535/50021019427_692a8167e9_k_d.jpg" width="100" />
<img src="https://live.staticflickr.com/65535/50020228418_d730efe386_k_d.jpg" width="100" />
<img src="https://live.staticflickr.com/65535/50020230828_7ef175d07c_k_d.jpg" width="100" />
<div style="background-image: url(https://live.staticflickr.com/65535/50020765826_e8da0aacca_k_d.jpg);"></div>
<style>
.bg {
background-image: url("https://live.staticflickr.com/65535/50020765651_af0962c22e_k_d.jpg");
}
</style>
<div class="bg"></div>
<div id="loadingProgress"></div>
该脚本将页面中的所有
src
和background-image
保存在数组中,并全部加载。您可以通过变量
loadCount
看到/阅读/显示加载进度。 let backgroundImageArray = [];
function backgroundLoading(i) {
let loadCount = 0;
let img = new Image();
$(img).on('load', function () {
if (i < backgroundImageArray.length) {
loadCount = parseInt(((100 / backgroundImageArray.length) * i));
backgroundLoading(i + 1);
} else {
loadCount = 100;
// do something when the page finished to load all the images
console.log('loading completed!!!');
$('#loadingProgress').append('<div>loading completed!!!</div>');
}
console.log(loadCount + '%');
$('#loadingProgress').append('<div>' + loadCount + '%</div>');
}).attr('src', backgroundImageArray[i - 1]);
}
$(document).ready(function () {
$('*').each(function () {
var backgroundImage = $(this).css('background-image');
var putInArray = false;
var check = backgroundImage.substr(0, 3);
if (check == 'url') {
backgroundImage = backgroundImage.split('url(').join('').split(')').join('');
backgroundImage = backgroundImage.replace('"', '');
backgroundImage = backgroundImage.replace('"', '');
if (backgroundImage.substr(0, 4) == 'http') {
backgroundImage = backgroundImage;
}
putInArray = true;
} else if ($(this).get(0).tagName == 'IMG') {
backgroundImage = $(this).attr('src');
putInArray = true;
}
if (putInArray) {
backgroundImageArray[backgroundImageArray.length] = backgroundImage;
}
});
backgroundLoading(1);
});
#19 楼
咖啡脚本中有5行array = ['/img/movie1.png','/img/movie2.png','/img/movie3.png']
$(document).ready ->
for index, image of array
img[index] = new Image()
img[index].src = image
评论
您能否扩展解决方案如何解决OP中的问题?并可能注释您的代码,以便其他人可以更轻松地理解它?
–Ro Yo Mi
13年8月10日在0:25
#20 楼
对于那些只懂一点动作脚本的人,您可以轻松地检查Flash Player,并制作Flash预加载器,也可以将其导出到html5 / Javascript / Jquery。如果Flash Player是未检测到,请查看有关如何使用youtube角色将其返回html5播放器的示例:)
并创建自己的示例。
我没有详细信息,因为我还没有开始,如果我没有忘了,我稍后再发布,将尝试一些标准的Jquery代码来挖掘。
评论
这不是解决方案。浏览器默认情况下不支持Flash Player。使用本机浏览器语言JavaScript可以轻松实现。
–乌斯曼·艾哈迈德(Usman Ahmed)
17年5月5日17:56
我记得2012年的Flash仇恨者...这是不正常的...到处走走,我什至都用Flash来攻击我。
– Peter Gruppelaar
17年5月6日在19:08
评论
$ .each(arguments,function(){(new Image).src = this});