要精确获取图片尺寸,核心方法就是等待图片完全加载完成。无论你需要获取图片的原始尺寸(naturalWidth 和 naturalHeight),还是它在页面中实际渲染后的尺寸(offsetWidth 和 offsetHeight),都不能在 DOM 刚加载完毕时立即读取。此时图片可能尚未加载完成,读取到的值往往是 0 或默认值。

确保图片加载完成后再获取尺寸
最可靠的方法是通过监听 load 事件。这种方式适用于 DOM 中已有的 元素,也适用于动态创建的图片。
- 为已有的图片绑定
load事件,在回调函数中即可安全地读取naturalWidth和naturalHeight。 - 注意一个陷阱:如果图片已被浏览器缓存,
load事件可能会同步触发。为保险起见,应首先检查complete属性——若返回true,则直接读取尺寸,无需等待事件触发。 - 动态创建图片时,操作顺序至关重要:必须先设置
src属性,然后再绑定load事件。反之,特别是在图片已缓存的情况下,很可能会错过事件回调。
获取图片渲染后的实际显示尺寸
如果需要了解图片在页面上实际占据的空间——例如受到 CSS 缩放或容器约束时——就需要查看布局相关属性。
offsetWidth/offsetHeight:最常用的属性,包含 padding 和 border 的可见尺寸,直接反映图片的视觉大小。clientWidth/clientHeight:表示内容区域尺寸,不包括 border 和滚动条,仅为内容框的大小。getBoundingClientRect():如果需要更高精度,例如处理小数位尺寸或获取图片相对于视口的精确位置,此方法是最佳选择。- 注意:这些值仅在图片完全渲染后有效。若不确定时机,可配合
requestAnimationFrame确保元素已挂载并可见。
批量处理多个图片,避免重复计算
当页面中包含大量图片时,逐一监听 load 事件可能会影响性能。以下是一些优化建议:
- 使用
document.querySelectorAll('img')一次性获取所有图片,然后遍历处理。 - 为每个图片添加标记,如
data-loaded="true",以避免重复绑定事件或重复读取尺寸。 - 对于懒加载图片,情况较复杂:不能期望图片一进入视口就获取尺寸。正确做法是使用
IntersectionObserver触发加载,待图片src实际设置并加载完成后,再读取尺寸。 - 如需统一处理多个图片的加载完成时机,可借助
Promise.all将它们的加载过程封装,待所有图片就绪后统一响应。
注意跨域图片的限制
跨域图片需要特别留意。读取 naturalWidth 和 naturalHeight 通常不受影响,但部分浏览器在严格模式下可能返回 0。更关键的是,如果后续要将图片绘制到 canvas 上,跨域未声明会直接抛出安全错误。
- 若图片服务器支持 CORS,可在
img标签上设置crossOrigin="anonymous"。 - 设置
crossOrigin后,服务器必须返回正确的Access-Control-Allow-Origin头部,否则图片加载将失败。 - 若不设置
crossOrigin,获取尺寸基本可行,但无法将其用于 canvas 中。
