我正在进行 Ajax 调用,它会返回一些信息,包括图像路径。
我在我的 HTML 中准备了所有这些信息,这些信息将显示为一种弹出窗口。我只是将弹出 div 的可见性从隐藏切换到可见。
要设置弹出 div 的位置,我必须根据图像的高度进行计算。因此,在设置位置并将可见性切换为可见之前,我必须等待图像加载以了解其尺寸。
我尝试了递归,setTimeout,完整的img属性,while循环的技巧......但没有成功。
那么,我该怎么做呢?也许我应该在我的 Ajax 调用中返回尺寸。
我正在进行 Ajax 调用,它会返回一些信息,包括图像路径。
我在我的 HTML 中准备了所有这些信息,这些信息将显示为一种弹出窗口。我只是将弹出 div 的可见性从隐藏切换到可见。
要设置弹出 div 的位置,我必须根据图像的高度进行计算。因此,在设置位置并将可见性切换为可见之前,我必须等待图像加载以了解其尺寸。
我尝试了递归,setTimeout,完整的img属性,while循环的技巧......但没有成功。
那么,我该怎么做呢?也许我应该在我的 Ajax 调用中返回尺寸。
var img = new Image();
img.onload = function() { alert("Height: " + this.height); }
img.src = "http://path/to/image.jpg";
请注意,按上述顺序执行此操作很重要:首先附加处理程序,然后设置src
. 如果您以相反的方式执行此操作,并且图像在缓存中,您可能会错过该事件。JavaScript 在浏览器中的单线程上运行(除非您使用网络工作者),但浏览器不是单线程的。浏览器看到src
、识别资源可用、加载它、触发事件、查看元素以查看它是否有任何需要排队等待回调的处理程序、看不到任何处理程序并完成事件是完全有效的处理,所有之间src
线和附加处理程序的线。(如果它们被注册,回调将不会在行之间发生,它们会在队列中等待,但如果没有,则事件不需要等待。)
如果你使用 jQuery,你可以使用它的load事件。
看看这个例子:
$('img.userIcon').load(function(){
if($(this).height() > 100) {
$(this).addClass('bigImg');
}
});
接受的答案已经过时,但确实显示了基本的Image#onload
回调方法。如今,您可能希望承诺图像加载以避免回调地狱。
这个答案很好地说明了图像加载处理程序,但正如我的评论所指出的那样,它缺少一些关键点。
这是另一个Image
更笼统的承诺。在onerror
处理程序中拒绝并将实际的图像对象传递给解析器对于使函数具有最小的可重用性很重要。
改进可能包括附加参数(例如crossOrigin
,例如)。一个settings
对象或提供一个Image
作为参数是另一种泛化函数的方法(设置src
触发请求,因此应该在添加处理程序后最后执行)。
const loadImage = src =>
new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
})
;
loadImage("http://placekitten.com/90/100").then(image =>
console.log(image, `\nloaded? ${image.complete}`)
);
使用上述功能,Promise.all
可用于并行加载一批图像(Promise.allSettled
如果您想在某些图像未加载的情况下继续运行,则很有用)。
const loadImage = src =>
new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
})
;
const imageUrls = [
"http://placekitten.com/85/150",
"http://placekitten.com/85/130",
"http://placekitten.com/85/110",
];
Promise.all(imageUrls.map(loadImage)).then(images => {
const canvas = document.createElement("canvas");
document.body.appendChild(canvas);
const ctx = canvas.getContext("2d");
images.forEach((image, i) =>
ctx.drawImage(image, i * 90, 0, image.width, image.height)
);
});
只需将您的图像 onload 包装在一个带有 promise 的函数中,然后使用 await 调用它。
async drawImg(ctx, image){
return new Promise(resolve => {
image.onload = function () {
ctx.drawImage(image, 10, 10, 200, 180);
resolve('resolved');
}
});
}
它应该可以正常工作
窗口加载事件怎么样?
window.addEventListener('load', (event) => {
//do stuff with images
});
或者
window.onload = (event) => {
//do stuff with images
};
https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
这对我有用,我需要浏览器在运行布局脚本之前计算图像的大小。
function waitForImage(imgElem) {
return new Promise(res => {
if (imgElem.complete) {
return res();
}
imgElem.onload = () => res();
imgElem.onerror = () => res();
});
}
// test
(async () => {
const img = document.querySelector('img');
// to not to cache, set src dynamically
img.src = 'https://www.gravatar.com/avatar/71094909be9f40bd576b1974a74966aa?s=48&d=identicon&r=PG&f=1';
console.log('height before', img.naturalHeight); // 0
await waitForImage(img);
console.log('height after', img.naturalHeight); // 48
})();
<img src=""/>
我的页面上加载了缓慢的 CAPTCHA (1st_image) 图像,我想仅在加载 CAPTCHA 图像 (1st_image) 后显示另一个图像 (2nd_image)。所以我不得不等待 CAPTCHA (1st_image) 图像首先加载。
这是一个完美的解决方案,可以先等待图像加载,然后再加载另一个图像(不要忘记在他们等待其他图像加载时显示“请稍候!”图像):
<script>
function checkImageLoad() {
if (document.getElementById("1st_image").complete == true) {
console.log("1st_image Loaded!");
}
document.getElementById("2nd_image").src = "http://example.org/2nd_image.png";
}
</script>
<body onload="checkImageLoad();">
<img id="1st_image" src="http://example.org/1st_image.png">
<img id="2nd_image" src="http://example.org/loading_please_wait.gif">
要么网速慢要么快,浏览器会等待整个页面加载完所有图片(即使它们是外部链接的)然后执行函数,所以只有在第一张图片加载后才会显示第二张图片美好的。
高级说明:您可以在图片的“src”中使用网页网址,先加载网页,然后再显示图片。目的是从外部网页加载 cookie,这可能会影响显示的第二张图像(如 CAPTCHA)。