利用canvas进行的图片压缩
涉及到手机拍照上传,因为有些照片比较大,影响客户体验,所以需要对照片进行压缩,简述一下压缩的原理就是利用canvas把图片重绘一遍,按照一定的质量比例。
这里贴上代码记录一下,方便以后使用
如果图片名字为image.jpg会串图,所以需要单独处理一下名字为image.jpg的图片。
js部分
// 图片获取
private upload(event: any) {
this.form['快照'] = [];
event.target.files.forEach((v: any, i: number) => {
this.preview(v, i);
});
}
private preview(file: any, index: number) { const reader = new FileReader(); const img = document.createElement('img'); img.id = `img${index}`; img.className = 'hide'; document.body.appendChild(img); const img_original: any = document.getElementById(`img${index}`); reader.onload = (e: any) => { img_original.src = e.target.result;// 这里的result是一个blob格式的数据,因为是多张上传所以用了这种写法,单张可以写成this.result,外层循环也可以去掉。 img_original.onload = () => { console.log('图片原始宽高:', img_original.naturalWidth, img_original.naturalHeight); console.log('图片原始大小:', file.size); }; }; reader.readAsDataURL(file); setTimeout(() => { this.compress(file, index); }, 1000);// 此处作为一个异步处理,因为图片越大压缩时间越久,所以如果出现压缩失败,或者图片显示失败可以把时间调长一些。 } // 图片压缩 private compress(file: any, index: number) { let blob; const document: any = window.document; // 压缩到图片原始宽高的一半 const img_original = document.getElementById(`img${index}`); const w = img_original.naturalWidth / 2; const h = img_original.naturalHeight / 2; const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const anw = document.createAttribute('width'); anw.nodeValue = w; const anh = document.createAttribute('height'); anh.nodeValue = h; canvas.setAttributeNode(anw); canvas.setAttributeNode(anh); ctx.fillRect(0, 0, w, h); ctx.drawImage(img_original, 0, 0, w, h); const base64 = canvas.toDataURL('image/jpeg', 0.4); // 压缩后质量 const bytes = window.atob(base64.split(',')[1]); const ab = new ArrayBuffer(bytes.length); const ia = new Uint8Array(ab); for (let i = 0; i < bytes.length; i++) { ia[i] = bytes.charCodeAt(i); } blob = new Blob([ab], {type: 'image/jpeg'}); this.imgFormat(blob, file); console.log('压缩后的图片大小', blob.size); }
h5部分
<img v-for="(item, index) in form['快照']" :key="index" :src="item" class="imgShow"/>
<!-- </div> -->
<div class="upload">
<img src="images/icon_add.png" />
<input class="file" type="file" @change="upload" accept=".jpg, .jpeg, .webp, .png, .bmp" multiple="multiple"/>
</div>
blob数据类型一般是二进制存储图像,音频等内容,可以直接在src后面跟上blob来显示对应的图像,音频想来也可以,不过目前并没有用到。
所以一个新的发现就是:src后面不一定要跟地址,blob数据也可以显示对应的内容。