等待图像在 JavaScript 中加载

新手上路,请多包涵

我正在进行 Ajax 调用,它会返回一些信息,包括图像路径。

我在我的 HTML 中准备了所有这些信息,这些信息将显示为一种弹出窗口。我只是将 by popup div 的可见性从隐藏切换为可见。

要设置弹出 div 的位置,我必须根据图像的高度进行计算。因此,在设置位置并将可见性切换为可见之前,我必须等待图像加载才能知道其尺寸。

我尝试了递归、setTimeout、完整的 img 属性、while 循环等技巧……但没有成功。

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

原文由 Jeenyus 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 326
2 个回答
var img = new Image();
img.onload = function() { alert("Height: " + this.height); }
img.src = "http://path/to/image.jpg";

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

原文由 Josh Stodola 发布,翻译遵循 CC BY-SA 3.0 许可协议

接受的答案 已过时,但确实显示了基本的 Image#onload 回调方法。如今,您可能希望承诺图像加载以避免回调地狱。

这个答案 很好地证明了图像加载处理程序,但如 我的评论 所示,缺少一些关键点。

这是 Image 的另一个 promisification,它更笼统一些。在 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)
  );
});

原文由 ggorlen 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题