img.width 和 img.height 返回的是渲染尺寸而非原始分辨率,只有在图片加载完成后的 image.onload 回调中读取 naturalwidth 和 naturalheight 才可靠,未加载完成时其值为 0。

直接用 img.width 和 img.height 拿到的几乎总是渲染尺寸,不是原始分辨率。必须等图片加载完成、读取 naturalWidth 和 naturalHeight 才可靠。
为什么 img.width 返回的不是原始宽高
img.width 和 img.height 对应的是 HTML 属性或 CSS 设置的显示尺寸,哪怕没设,浏览器也会按图像自然尺寸渲染——但这个“渲染尺寸”可能已被缩放、裁剪或响应式样式干扰。真正代表像素数的只有 naturalWidth 和 naturalHeight,它们只在图片加载完成后才有效。
- 未加载完成时读取,值为 0
- 加载后即使设置了
width="200",naturalWidth仍是原始像素宽度(比如 1920) - CSS 的
max-width: 100%或transform: scale()完全不影响natural*值
上传后立即读取 naturalWidth 的正确时机
不能在 FileReader 的 onload 回调里直接 new Image() 就读 —— 那时只是 base64 字符串就绪,Image 还没解码。必须监听 image.onload。
- 先用
FileReader把File转成dataURL - 再创建
new Image(),赋值src为该 dataURL - 在
image.onload中读取image.naturalWidth和image.naturalHeight - 如果
image.naturalWidth === 0,说明加载失败(比如损坏、跨域、格式不支持),需 fallback
示例关键逻辑:
const reader = new FileReader();
reader.onload = () => {
const img = new Image();
img.onload = () => {
console.log('原始宽高:', img.naturalWidth, img.naturalHeight);
};
img.onerror = () => console.error('图片解码失败');
img.src = reader.result; // dataURL
};
reader.readAsDataURL(file);
常见坑:动态创建 img 标签却忘了加 src 或 onload
很多人写成 const img = new Image(); img.src = url; 就直接读 naturalWidth,结果是 0。因为赋值 src 是异步触发加载,不等 onload 就读,必然为空。
- 不要用
img.width/img.height替代natural* - 不要依赖
offsetWidth、clientWidth或getComputedStyle—— 它们返回的是布局尺寸 - 避免在
FileReader.onload外部直接访问img.naturalWidth - 移动端某些 WebView(如旧版 UC)对 dataURL 解码有延迟,可加
setTimeout保险,但优先走 onload
原始分辨率这事,本质是图像解码完成的信号问题。只要守住 image.onload 这个边界,naturalWidth 就不会骗人;越过去一步,拿到的就是错的。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











