Two days ago, I made a function to convert images to base64 for uploading. I found that if the base64 of the image is too large, the request will become very slow, and it will time out seriously, so I thought of compressing the image before uploading, and then uploading it to the background. , which can greatly improve efficiency. Here are some pitfalls encountered when using canvas to compress images. The complete code will be given at the end of the article.
The first pitfall is that when compressing the image, the width and height of the image itself are not obtained, and a fixed width and height of 600*480 is given. Because it is on the mobile phone, when uploading the image, the image is several megabytes in size, so this No problem. The problem occurred when modifying the avatar. The pictures uploaded during the test were all small pictures, and then the compressed pictures were not displayed completely, and most of them were blank. This is because they were not considered during the compression. The original width and height of the image.
The second pitfall. The way to solve the first pitfall is to obtain the width and height of the image itself after the image is loaded (onload), and then assign it to the canvas. This operation is performed in this way. However, the pitfall is that the image loading is asynchronous. , when you return, what is returned may be undefined instead of the compressed base64 you need. The solution here is to create a new Promise, then return the result resolve(), and get the result when calling .then().
Knowledge points:miniImage.js
export default async function miniSize(imgData, maxSize = 200*1024){ // const maxSize = 200 * 1024; if(imgData && imgData.files && imgData.files.size < maxSize) { return imgData.url; }else{ console .log('----------------Compressed image------------------'); const canvas = document.createElement('canvas'); let img = new Image(); img.src = imgData.url; let ctx = canvas.getContext('2d'); return new Promise((resolve =>{ img.addEventListener( 'load', function(){ //Original size of the picture let originWidth = this.width; let originHeight = this.height; // Maximum size limit let maxWidth = 400, maxHeight = 400; // Target size let targetWidth = originWidth, targetHeight = originHeight; // Image size exceeds the limit of 400x400 if (originWidth > maxWidth || originHeight > maxHeight) { if (originWidth / originHeight > maxWidth / maxHeight) { // Wider, limit size according to width targetWidth = maxWidth; targetHeight = Math.round(maxWidth * (originHeight / originWidth)); } else { targetHeight = maxHeight; targetWidth = Math.round(maxHeight * (originWidth / originHeight)); } } canvas.width = targetWidth; canvas.height = targetHeight; ctx.drawImage(img, 0, 0, targetWidth, targetHeight); let base64 = canvas.toDataURL('image/png', 0.9); resolve(base64); }, false); })) }}
Call:
test.js
onChangeImg = async (files, type, index) => { let previous = this.props.imagePicker.files; if(type === add) { let result = miniSize(files[files.length-1]); // Use .then() to call await result.then(res => { previous.push({url: res}); }); }else if(type === remove) { previous.splice(index,1); } await this.props.dispatch({ type: 'imagePicker/saveImage', payload: { files: previous } }) }
The above is the entire content of this article. I hope it will be helpful to everyone’s study. I also hope everyone will support VeVb Wulin Network.