一、选择拍照或文件
HTML:
使用<input>
标签,
type
设为"file"
选择文件,
a
ccept
设为"image/*"
选择文件为图片类型和相机拍摄,
设置multiple
支持多选。
<div class="add-image"> <input class="file" type="file" accept="image/*" multiple @change="onFileChange"> <div class="add" > <img src="../../assets/add/icon_addphoto.png" alt> <p>添加照片</p> </div> </div>
样式:
设置opacity为0,使用自定义div覆盖于上面
.add-image{ width: 148px; height: 148px; position: relative;
.file{ position: absolute; top: 0; left: 0; width: 148px; height: 148px; opacity: 0; }
效果:
二、图片预览
VUE数据驱动更新前端所展示图片
两种方式:
1、使用本地URL(如果项目需要整理服务器图片地址作为表单提交,则本地URL不可以使用,操作删除不便)
URL.createObjectURL
方法可创建一个本地的 URL 路径指向本地资源对象,下面使用该接口创建所选图片的地址并展示。
let url=window.URL.createObjectURL(file) this.goods.goodsImageList.push(url)
2、使用服务器返回路径(缺点:如果上传失败就无法显示)
上传图片请求成功后,服务器返回一个url,使用该url进行字符串拼接,然后加入goods.goodsImageList数组。
三、图片旋转
通过相机拍摄的图片,由于拍摄时手持相机的方向问题,导致拍摄的图片可能存在旋转,需要进行纠正。纠正旋转需要知道图片的旋转信息,这里借助了一个叫
exif-js 的库,该库可以读取图片的 EXIF 元数据,其中包括拍摄时相机的方向,根据这个方向可以推算出图片的旋转信息。
下面是 EXIF 旋转标志位,总共有 8 种,但是通过相机拍摄时只能产生1、3、6、8 四种,分别对应相机正常、顺时针旋转180°、逆时针旋转90°、顺时针旋转90°时所拍摄的照片。
纠正图片旋转角度,只要读取图片的 EXIF 旋转标志位,判断旋转角度,在画布上对图片进行旋转后,重新导出新的图片即可。
/** * 修正图片旋转角度问题 * @param {file} 原图片 * @return {Promise} resolved promise 返回纠正后的新图片 */ function fixImageOrientation (file) { return new Promise((resolve, reject) => { // 获取图片 const img = new Image(); img.src = window.URL.createObjectURL(file); img.onerror = () => resolve(file); img.onload = () => { // 获取图片元数据(EXIF 变量是引入的 exif-js 库暴露的全局变量) EXIF.getData(img, function() { // 获取图片旋转标志位 var orientation = EXIF.getTag(this, "Orientation"); // 根据旋转角度,在画布上对图片进行旋转 if (orientation === 3 || orientation === 6 || orientation === 8) { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); switch (orientation) { case 3: // 旋转180° canvas.width = img.width; canvas.height = img.height; ctx.rotate((180 * Math.PI) / 180); ctx.drawImage(img, -img.width, -img.height, img.width, img.height); break; case 6: // 旋转90° canvas.width = img.height; canvas.height = img.width; ctx.rotate((90 * Math.PI) / 180); ctx.drawImage(img, 0, -img.height, img.width, img.height); break; case 8: // 旋转-90° canvas.width = img.height; canvas.height = img.width; ctx.rotate((-90 * Math.PI) / 180); ctx.drawImage(img, -img.width, 0, img.width, img.height); break; } // 返回新图片 canvas.toBlob(file => resolve(file), 'image/jpeg', 0.92) } else { return resolve(file); } }); }; }); }
四、图片压缩
现在手机拍照质量越来越高,拍出来的照片多达几M甚至十几M,直接上传原图不合理,容易上传失败,且后台对请求体大小有限制,后续加载图片展示也会变得慢,所以要求我们前端在上传之前进行图片的压缩。
下面函数实现了对图片的压缩,原理是在画布上绘制缩放后的图片,最终从画布导出压缩后的图片。方法中有两处可以对图片进行压缩控制:一处是控制图片的缩放比;另一处是控制导出图片的质量。
// 压缩图片 compressImage(file) { return new Promise((resolve, reject) => { const img = new Image(); img.src = window.URL.createObjectURL(file); img.onerror = error => reject(error); img.onload = () => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = Mat