Vue图片处理解决方案,一篇就够了

一、阅读须知

小帅爆肝整理的这篇文章,内容比较多,帅帅的你值得看一看,有解决方案的核心代码,放到项目中可以直接使用
最近还会更新关于“图片横向合并、纵向合并、图片编辑”的另一篇文章,敬请期待!

二、解决的问题

  • 使用canvas处理图片旋转、导入问题
  • 目前来看,在前端对图片文件进行处理,再传到服务端,性能上是可以的,不必要图片处理逻辑在服务端实现

三、知识储备

  1. 使用<input type="file">标签得到的File文件格式对象如下
    在这里插入图片描述
  2. 图片Base64编码的格式(可以直接使用<img> <el-image>标签进行渲染)
    在这里插入图片描述

四、解决方案

如果使用canvas实现对图片的旋转目前有两种方案

  1. 利用canvas的translate()平移函数 + rotate()旋转函数 + drawImage()函数 实现,这种方式存在更复杂的数学计算问题
  2. 利用canvas的 rotate()旋转函数 + drawImage()函数 实现(本篇使用的解决方案),下文提供代码案例

五、核心代码

  • 解决方案2对应的核心代码,解决将图片顺时针旋转90°、180°、270°问题
  • 如下代码drawImage()函数中的img参数为new Image()对象,或者其它符合函数要求的参数类型
// 创建canvas
const selfCanvas = document.createElement('canvas')
const selfCtx = selfCanvas.getContext('2d')

if (angle == '90') {
    
     // 顺时针旋转90度
  selfCanvas.width = img.height
  selfCanvas.height = img.width
  selfCtx.rotate(90 * Math.PI / 180);
  selfCtx.drawImage(img, 0, 0, img.width, -img.height)       
} else if (angle == '180') {
    
     // 顺时针旋转180度
  selfCanvas.width = img.width
  selfCanvas.height = img.height
  selfCtx.rotate(180 * Math.PI / 180)
  selfCtx.drawImage(img, -img.width, -img.height, img.width, img.height)
} else if (angle == '270') {
    
     // 顺时针旋转270度
  selfCanvas.width = img.height
  selfCanvas.height = img.width
  selfCtx.rotate(270 * Math.PI / 180)
  selfCtx.drawImage(img, -img.width, 0, img.width, img.height)        
} else {
    
     // 不进行任何旋转
  selfCanvas.width = img.width
  selfCanvas.height = img.height
  selfCtx.drawImage(img, 0, 0, img.width, img.height)
}

六、参考资料

  1. 得到图片文件File的URL
img.src = URL.createObjectURL(imgFile)
  1. 相关api函数方法
  • createObjectURL(obj):返回一个URL 对象表示指定的 File 对象(生成blob:http://www.xxxx.com/xx的链接,可以直接在网页上打开File内容)或 Blob 对象(用于下载),obj为 File 对象、Blob 对象或者 MediaSource 对象
  • revokeObjectURL(objURL):在每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放,objURL为URL.createObjectURL(obj) 返回的对象
  • arr = new Uint8Array(length):返回一个长度为length的8位无符号整型数组(存储大小为0~256,负数会自动加256转为整数,超出-256),创建时内容被初始化为0
  • new Blob(arr,options):返回一个blob对象(可理解为二进制的数据对象),常用用于文件下载
  • canvas.toBlob(callback, type, quality):创造 Blob 对象,用以展示 canvas 上的图片;这个图片文件可以被缓存或保存到本地,具体参数:
    • allback:回调函数,可获得一个单独的 Blob 对象参数。如果图像未被成功创建,可能会获得 null 值
    • type:指定图片格式,默认格式(未指定或不支持)为 image/png
    • quality:值在 0 与 1 之间,当请求图片格式为 image/jpeg 或者 image/webp 时用来指定图片展示质量。如果这个参数的值不在指定类型与范围之内
  1. 在h5中,使用input的type="file"和capture="camera"这两个属性就可以调用摄像头
  2. 如果使用document.createElement()动态创建的元素,通过如下的方法得到输入的值
// 创建一个input元素
var inputElem = document.createElement("input");
// 获取input的值
var inputValue = inputElem.value;
// 如果input标签type="file"
// 得到文件对象File
var file = inputElem.files
  1. 如果input标签不是动态创建的,是已经写好的html元素,则可以在change=“methodsName(e)”,通过e.target.files获得文件对象
  2. Vue中可以使用如下方式添加、移除事件
// 绑定事件 可以进行监听
addEventListener()
// 移除事件
removeEventListener()
  1. 关于<input>标签中的webkitdirectory属性参考:https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLInputElement/webkitdirectory
  2. 使用FormData对象上传文件
const formData = new FormData()
formData.append('file', File)

七、FileReader()对象

  • FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
  • FileReader实例拥有4个方法,3个用来读取文件,一个用来中断读取
    • abort 参数none 中断读取
    • readAsBinaryString 参数file 将文件读取为二进制码
    • readAsDataUrl 参数file 将文件读取为data:开头的字符串,实质就是Data URL 是将小文件(图像等)直接嵌入文档的方案,base64的方式由此来获得
    • readAsText file,[encoding] 文本方式读取文件,读取结果是文本的内容
  • 读取结果会存储在FileReader的result属性中,处理事件简介:
    • onabort 中断时触发
    • onerror 出错时触发
    • onload 读取成功时触发
    • onloadend 读取完成时触发 无论成功失败
    • onloadstart 读取开始时触发
    • onprogress 读取中
  • 文件开始读取后无论成功失败都会填充result属性,读取失败result属性会赋值null,否则会填充读取结果
  • onload读取成功之后,直接将base64赋值给img元素的src属性,就可以预览图片了
  • 使用FileReader对象将File转成base64代码案例
// 图片file转base64方法(file文件,回调函数)
  fileToBase64(file, callback) {
    
    
    // 创建FileReader对象(不兼容IE)
    let reader = new FileReader();
    // 将file转为base64 (异步操作)
    reader.readAsDataURL(file); 
    // 转换成功
    reader.onload = () => {
    
    
      const response = {
    
    
        status: true,
        data: reader.result
      }
      callback(response);
    };
    // 转换失败
    reader.onerror = function () {
    
    
      const response = {
    
    
        status: false,
        data: reader.error
      }
      callback(response);
    };
  }

// 调用方法
fileToBase64(imgFile, (res) => {
    
    
  if(res.status) {
    
    
    console.log('file转化成base64成功---',res.data)
  } else {
    
    
    console.log('file转化base64失败---',res.data)
  }
})

八、Exif库使用

  1. 用Exif获取图像的原始数据,例如:拍照方向,拍摄事件,ISO感光度,GPS地理位置等数据
  2. vue中引入exif-js
npm install exif-js --save   
  1. Exif提供的部分API方法
    • Exif.getData(img,callback) 获取图像数据
    • Exif.getTag(img,tag) 获取图像的某个数据
    • Exif.getAllTags(img) 获取图像的全部数据
    • Exif.pretty(img) 获取图像的全部数据,值以字符串的形式范围
  • 其中Exif中orientation不同的值代表不同的方向
  1. Exif的npm仓库地址:https://www.npmjs.com/package/exif-js
  2. Exif的GitHub地址:https://github.com/exif-js/exif-js
    上述两个地址里面有使用参考文档
  3. 前端开发工具箱:http://code.ciaoca.com/

九、Canvas画布

  1. canvas是一个容器(画布),他的getContext()方法用来获取一个对象,这个对象提供了在画布上绘图的方法和属性
  2. 菜鸟教程中关于canvas资料:https://www.runoob.com/tags/ref-canvas.html
  3. w3school中的canvas资料:https://www.w3school.com.cn/jsref/dom_obj_canvas.asp
  4. 资料网站:https://www.twle.cn/l/yufei/canvas/canvas-basic-index.html

十、动态创建标签并添加绑定事件

var input = document.createElement('input'); 
input.setAttribute('value', ''); 
input.setAttribute('type', 'text'); 
input.setAttribute('class', 'my-custom-input'); 

document.body.appendChild(input); 

//Change event listener 
input.addEventListener('change', function(e) {
    
     
    console.log('I just changed'); 
}, false);

十一、utils方法

  1. 从base64代码中获取图片的宽高
var i = new Image();  //创建一个临时存储
i.onload = function(){
    
      //定义加载图片后弹出显示
 alert( i.width+", "+i.height );
};
i.src = imageData //将图片数据赋值即可
  1. base64转文件
dataURLtoFile(dataurl) {
    
    
    var arr = dataurl.split(',')
    var bstr = atob(arr[1])
    var n = bstr.length
    var u8arr = new Uint8Array(n)
    while (n--) {
    
    
      u8arr[n] = bstr.charCodeAt(n)
    }
    return new File([u8arr], 'image', {
    
    
      type: 'image'
    })
  }

十二、vue中图片预览

  1. 使用远程的<img>标签
  2. 使用element-ui的<el-image>标签
  3. 使用element-ui的<el-image-viewer>
<el-image-viewer v-if="imgViewerVisible" :on-close="closeImgViewer" :url-list="imgList" />
  1. 使用v-viewer库

十三、工具网站

  1. base64转图片:http://www.atoolbox.net/Tool.php?Id=1024
  2. vue图片裁剪插件(vue-picture-cut 2.x):https://gitee.com/light-year/vue-picture-cut

猜你喜欢

转载自blog.csdn.net/baidu_38493460/article/details/130739528