Angular集成Resize-Base64遇drawImage执行失败问题排查
问题根源:图片加载是异步操作
兄弟,你踩了一个前端非常常见的坑——当你给img.src赋值Base64字符串后,浏览器不会立刻完成图片的解析和加载,这是个异步操作。你现在的代码刚设置完img.src就去读取img.width和img.height,这时候图片还没加载好,这两个值自然都是0,后续调用drawImage肯定会抛出错误。
解决方案:用
onload等待图片加载完成再执行逻辑 图片对象自带onload事件,会在图片完全加载成功后触发,我们需要把所有依赖图片宽高的逻辑都放到这个回调里。考虑到你用的是Angular,用Promise封装这个异步操作会更符合项目的编程风格,也方便用async/await处理结果。
改造Resize-Base64模块(改成Promise风格)
module.exports = function(base64, maxWidth = 500, maxHeight = 500){ console.log('base64 = ', base64); console.log('maxWidth = ', maxWidth); console.log('maxHeight = ', maxHeight); return new Promise((resolve, reject) => { const img = new Image(); // 图片加载成功后执行核心缩放逻辑 img.onload = function() { // 计算缩放比例 let ratio = 1; if(img.width > maxWidth) { ratio = maxWidth / img.width; } else if(img.height > maxHeight) { ratio = maxHeight / img.height; } // 初始化画布 const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); const canvasCopy = document.createElement("canvas"); const copyContext = canvasCopy.getContext("2d"); canvas.setAttribute('id', 'resize-base64'); // 先把原图绘制到临时画布 canvasCopy.width = img.width; canvasCopy.height = img.height; copyContext.drawImage(img, 0, 0); // 缩放绘制到目标画布 canvas.width = img.width * ratio; canvas.height = img.height * ratio; console.log(' canvas.width = ', canvas.width); console.log(' canvas.height = ', canvas.height ); ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height); // 返回压缩后的Base64(也可以返回canvas对象,根据你的需求调整) resolve(canvas.toDataURL()); }; // 处理图片加载失败的情况 img.onerror = function(err) { reject(new Error('加载Base64图片失败,请检查格式是否正确')); }; // 最后设置src,触发图片加载 img.src = base64; }); }
调整Angular组件的调用方式
现在模块返回的是Promise,我们用async/await来处理异步结果,代码会更清晰易读:
async setLargeImageDimensions(resetBase64Image) { try { // 等待图片压缩完成 const resizedBase64 = await resizebase64(resetBase64Image, 1000, 1000); // 这里可以把结果赋值给组件变量,比如用于页面展示 console.log('压缩后的图片Base64:', resizedBase64); } catch (error) { console.error('图片压缩出错:', error); } }
额外要注意的细节
- 检查你的Base64字符串是否有正确的前缀,比如
data:image/jpeg;base64,,如果缺了这个前缀,图片可能加载失败触发onerror。 - 原代码最后返回
maxWidth明显是个笔误,我改成返回压缩后的Base64了,你可以根据自己的需求调整返回值(比如返回canvas对象)。 - 如果你的Base64图片特别大,加载时间会稍长,但
onload回调能保证逻辑在图片完全就绪后执行,不用担心宽高为0的问题。
内容的提问来源于stack exchange,提问作者user8516249
相关产品推荐
相关产品推荐

