等待图像加载Javascript

Jee*_*yus 55 javascript load image wait

我正在进行Ajax调用,它会返回一些信息,包括图像路径.我在HTML中准备了所有这些信息,这些信息将显示为一种弹出窗口.我只是将popup div的可见性从隐藏切换为可见.

要设置弹出窗口div的位置,我必须根据图像的高度进行计算.因此,在设置位置和将可见性切换为可见之前,我必须等待图像加载以了解其尺寸.

我尝试了递归,setTimeout,完成img属性的技巧,而循环...没有成功.

那么,我该怎么做呢.也许我应该在Ajax调用中返回维度.

Jos*_*ola 104

var img = new Image();
img.onload = function() { alert("Height: " + this.height); }
img.src = "http://path/to/image.jpg";
Run Code Online (Sandbox Code Playgroud)

请注意,按上述顺序执行此操作非常重要:首先附加处理程序,然后设置src.如果你反过来这样做,并且图像在缓存中,你可能会错过这个事件.JavaScript在浏览器中的单个线程上运行(除非您使用的是Web工作者),但浏览器不是单线程的.浏览器看到src,识别资源是否可用,加载它,触发事件,查看元素是否有任何需要排队等待回调的处理程序,看不到任何处理程序,并完成事件是完全有效的.处理,所有src行和连接处理程序的行之间.(如果它们被注册,它们之间不会发生回调,它们会在队列中等待,但如果没有,则不需要等待事件.)

  • @Marco或者在XHR上设置`cache:false` :)虽然我认为它不相关,因为AJAX调用返回的是图像的URL,而不是图像本身.但是,我想他仍然可以使用随机查询字符串值来确保不会发生用户代理缓存. (2认同)
  • @IQAndreas:你可以使用`img.addEventListener("load", ...)`,是的。(或旧 IE 上的 `img.attachEvent("onload", ...)`)。 (2认同)

ggo*_*len 17

接受的答案已经过时,但确实显示了基本的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}`)
);
Run Code Online (Sandbox Code Playgroud)

通过上述函数,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)
  );
});
Run Code Online (Sandbox Code Playgroud)


Sag*_*agi 12

如果使用jQuery,则可以使用其load事件.

看看这个例子:

$('img.userIcon').load(function(){
    if($(this).height() > 100) {
        $(this).addClass('bigImg');
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 除非请求jquery,否则请不要使用jquery (64认同)
  • -1:在问题中没有提到jQuery,所以像这样的答案可能会让人很困惑. (9认同)
  • 当与图像一起使用时,请注意以下有关加载方法的注意事项(摘自http://api.jquery.com/load-event/):>它不能一致地工作,也不能可靠地跨浏览器>它没有如果图像src设置为与之前相同的src,则在WebKit中正确触发>它没有正确地冒泡DOM树>可以停止为已经存在于浏览器缓存中的图像触发 (3认同)

ya_*_*mon 9

等待图像的函数,该图像已经在 HTML 中

承诺的例子。不拒绝只是等待加载或失败:

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 in the test, 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
})();
Run Code Online (Sandbox Code Playgroud)
<img src=""/>
Run Code Online (Sandbox Code Playgroud)

带有拒绝的版本,如果您需要知道它是否失败:

function waitForImage(imgElem) {
    return new Promise((res, rej) => {
        if (imgElem.complete) {
            return res();
        }
        imgElem.onload = () => res();
        imgElem.onerror = () => rej(imgElem);
    });
}



// test
(async () => {
  const img = document.querySelector('#rightone');
  // to not to cache in the test, 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); // success
  console.log('height after', img.naturalHeight); // 48

  try {
    const failImg = document.querySelector('#wrongone');
    failImg.src = 'https://wrongimage';
    await waitForImage(failImg); // rejects after some time
  } catch(e) {
    console.log('failed to load image', e)
  }


})();
Run Code Online (Sandbox Code Playgroud)
<img id="rightone" src="">
<img id="wrongone" src="">
Run Code Online (Sandbox Code Playgroud)