Javascript - 在所有图像加载后执行
Javascript - execute after all images have loaded
读过别人的问题,我想
window.onload=...
会回答我的问题。我已经尝试过了,但它在页面加载的那一刻(而不是在图像加载后)执行代码。
如果有任何区别,图像来自CDN,而不是相对的。
有人知道解决方案吗?(我没有使用jQuery)
想要一行吗?
Promise.all(Array.from(document.images).filter(img => !img.complete).map(img => new Promise(resolve => { img.onload = img.onerror = resolve; }))).then(() => {
console.log('images finished loading');
});
相当向后兼容,甚至可以在Firefox 52和Chrome 49(Windows XP时代)中使用。但是,在IE11中不是。
将document.images
替换为例如 document.querySelectorAll(...)
是否要缩小图像列表的范围。
它使用onload
和onerror
来简洁。如果 img
元素的这些处理程序也在其他地方设置,则这可能会与页面上的其他代码冲突(不太可能,但无论如何)。如果您不确定您的页面是否不使用它们并希望安全,请将img.onload = img.onerror = resolve;
部分替换为更长的部分:img.addEventListener('load', resolve); img.addEventListener('error', resolve);
。
它也不会测试是否所有图像都已成功加载(没有损坏的图像)。如果需要,这里有一些更高级的代码:
Promise.all(Array.from(document.images).map(img => {
if (img.complete)
return Promise.resolve(img.naturalHeight !== 0);
return new Promise(resolve => {
img.addEventListener('load', () => resolve(true));
img.addEventListener('error', () => resolve(false));
});
})).then(results => {
if (results.every(res => res))
console.log('all images loaded successfully');
else
console.log('some images failed to load, all finished loading');
});
它会等待,直到所有图像都加载或加载失败。
如果您想提前失败,使用第一个损坏的映像:
Promise.all(Array.from(document.images).map(img => {
if (img.complete)
if (img.naturalHeight !== 0)
return Promise.resolve();
else
return Promise.reject(img);
return new Promise((resolve, reject) => {
img.addEventListener('load', resolve);
img.addEventListener('error', () => reject(img));
});
})).then(() => {
console.log('all images loaded successfully');
}, badImg => {
console.log('some image failed to load, others may still be loading');
console.log('first broken image:', badImg);
});
两个最新的代码块使用 naturalHeight
来检测已加载图像中的损坏图像。此方法通常有效,但有一些缺点:当通过 CSS content
属性设置图像 URL 时,以及当图像是未指定其尺寸的 SVG 时,据说它不起作用。如果是这种情况,则必须重构代码,以便在图像开始加载之前设置事件处理程序。这可以通过在 HTML 中指定onload
和onerror
或在 JavaScript 中创建img
元素来完成。另一种方法是在 HTML 中src
设置为data-src
,并在附加处理程序后执行img.src = img.dataset.src
。
以下是现代浏览器的快速技巧:
var imgs = document.images,
len = imgs.length,
counter = 0;
[].forEach.call( imgs, function( img ) {
if(img.complete)
incrementCounter();
else
img.addEventListener( 'load', incrementCounter, false );
} );
function incrementCounter() {
counter++;
if ( counter === len ) {
console.log( 'All images loaded!' );
}
}
加载所有图像后,您的主机将显示"所有图像已加载!
此代码的作用:
- 从文档中加载变量中的所有图像
- 循环浏览这些图像
- 在每个图像上为"load"事件添加一个侦听器以运行
incrementCounter
函数 incrementCounter
将递增计数器- 如果计数器已达到图像的长度,则表示它们已全部加载
以跨浏览器方式拥有这段代码不会那么难,只是像这样更干净。
Promise Pattern 将以我所提到的最好的方式解决这个问题.js一个开源库来解决所有图像加载的问题
function loadImage (src) {
var deferred = when.defer(),
img = document.createElement('img');
img.onload = function () {
deferred.resolve(img);
};
img.onerror = function () {
deferred.reject(new Error('Image not found: ' + src));
};
img.src = src;
// Return only the promise, so that the caller cannot
// resolve, reject, or otherwise muck with the original deferred.
return deferred.promise;
}
function loadImages(srcs) {
// srcs = array of image src urls
// Array to hold deferred for each image being loaded
var deferreds = [];
// Call loadImage for each src, and push the returned deferred
// onto the deferreds array
for(var i = 0, len = srcs.length; i < len; i++) {
deferreds.push(loadImage(srcs[i]));
// NOTE: We could push only the promise, but since this array never
// leaves the loadImages function, it's ok to push the whole
// deferred. No one can gain access to them.
// However, if this array were exposed (e.g. via return value),
// it would be better to push only the promise.
}
// Return a new promise that will resolve only when all the
// promises in deferreds have resolved.
// NOTE: when.all returns only a promise, not a deferred, so
// this is safe to expose to the caller.
return when.all(deferreds);
}
loadImages(imageSrcArray).then(
function gotEm(imageArray) {
doFancyStuffWithImages(imageArray);
return imageArray.length;
},
function doh(err) {
handleError(err);
}
).then(
function shout (count) {
// This will happen after gotEm() and count is the value
// returned by gotEm()
alert('see my new ' + count + ' images?');
}
);
使用 window.onload
将不起作用,因为它会在加载页面后触发,但是图像不包括在此加载定义中。
对此的一般解决方案是 ImagesLoaded jQuery 插件。
如果你热衷于根本不使用jQuery,你至少可以尝试将这个插件转换为纯Javascript。在 93 行重要的代码和良好的注释中,这应该不是一项艰巨的任务。
您可以在图像上具有 onload 事件,该事件可以回调执行处理的函数...关于如何处理是否加载了所有图像,我不确定以下任何机制是否有效:
有一个函数来计算调用 Onload 的图像数量,如果这等于页面上的图像总数,则进行必要的处理。
<title>Pre Loading...</title>
</head>
<style type="text/css" media="screen"> html, body{ margin:0;
padding:0; overflow:auto; }
#loading{ position:fixed; width:100%; height:100%; position:absolute; z-index:1; ackground:white url(loader.gif) no-repeat center; }**
</style>
<script> function loaded(){
document.getElementById("loading").style.visibility = "hidden"; }
</script>
<body onload="loaded();"> <div id="loading"></div>
<img id="img" src="avatar8.jpg" title="AVATAR" alt="Picture of Avatar
movie" />
</body>
我一直在寻找这样的东西,如果你不介意使用 setInterval,这段代码既简单又直接。就我而言,我可以使用 setInterval,因为它可能会运行 4-5 次。
const interval = setInterval(() => {
const allImagesLoaded = [...document.querySelectorAll('img')]
.map(x => x.complete)
.indexOf(false) === -1;
if (allImagesLoaded) {
window.print();
clearInterval(interval);
}
}, 500);
这是Florian Margaine方法的略有不同。这考虑了其中一个图像中可能断开的链接。如果您仍然需要使用图像(例如,使用它们的高度来计算另一个元素在加载时的高度),这允许您这样做。
let imgs = document.querySelectorAll("img"),
counter = 0;
// Loop through images/check if it's loaded/if it is, increment the counter/else listen for when it does load and increment then
imgs.forEach((img) => (img.complete ? incrementCounter() : img.addEventListener("load", incrementCounter, false)));
function incrementCounter() {
counter++;
// If at least 1 image is loaded, do something
if (counter !== 0) {
calculateHeight();
}
}
我正要建议Baz1nga所说的同样的事情。
此外,另一个可能不是万无一失但更易于维护的选项是选择最重要/最大的图像,并仅将 onload 事件附加到该图像。这样做的好处是,如果您稍后向页面添加更多图像,则要更改的代码更少。
很好用:
$(function() {
$(window).bind("load", function() {
// code here
});
});
- 无法在通过jQuery的ajax加载的页面中执行javascript
- 在使用Polymer'加载所有json文件后执行方法;s的核心ajax
- 如何在从浏览缓存加载页面时执行javascript
- Jquery:代码在rails中的页面加载时未执行
- 如何准确执行加载脚本&退出弹出窗口
- 页面在我的javascript执行后重新加载,我不希望它这样做
- 加载服务器端渲染的React组件后执行脚本
- jQuery-在页面加载时执行一个函数
- ajax加载了内容,脚本没有执行
- 如何在加载完整页面后严格执行javascript代码
- 在动态加载的对话框中执行Javascript
- Dojo AMD加载程序执行定义具有空/缺失依赖项的回调
- 通过AJAX加载页面并执行javascript和CSS
- 返回上一页,不加载执行正文
- 谷歌自定义搜索 - 从网址参数手动加载/执行
- jquery文档就绪侦听器与图像加载;执行顺序
- 发现jsphp加载/执行问题
- jQuery ready()是否在所有JS文件加载/执行后触发
- 如何在加载/执行页面的任何其他脚本之前将Javascript注入/执行到页面中
- 在视图页面加载执行控制器功能,angularjs方式