前言

最近项目中遇得到了很多跟图片相关的技术点,这里主要是汇总一下,以备后期参考

1、前端二维码的生成与下载(兼容ie)

二维码生成

这里用了一个现有插件vue-qr
下载该插件

  1. npm i vue-qr
  2. 复制代码

在项目中引入该插件

  1. import VueQr from 'vue-qr'
  2. 复制代码

使用vue-qr

  1. <el-dialog
  2. :area="[520, 400]"
  3. top="middle"
  4. no-scrollbar
  5. title="小区二维码"
  6. :visible.sync="qrCodeDia"
  7. >
  8. <el-alert
  9. style="width: 105%;margin-left: -12px;margin-top: -12px;"
  10. title="请张贴此二维码于小区/单位内,居民扫描此二维码可录入人员信息。"
  11. type="info"
  12. simple
  13. show-icon
  14. :closable="false"
  15. ></el-alert>
  16. <div v-if="qrCodeDia" id="qrcode" style="text-align: center;margin-top: 24px;">
  17. <vue-qr :text="config.value" :size="200" :margin="0"></vue-qr>
  18. </div>
  19. <div slot="footer" class="dialog-footer">
  20. <el-button @click="downloadImg()">
  21. 下载
  22. </el-button>
  23. </div>
  24. </el-dialog>
  25. 复制代码

对应生成二维码与下载方法

  1. /**
  2. * @desc 展开二维码弹框
  3. */
  4. async handleShowQr(item) {
  5. const { data } = await httpAdress.getServerInfo()
  6. const http =
  7. data.scheme + '://' + data.ip + ':' + data.port + '/ossrs/app#/AddPerson/' + item.id
  8. this.config.value = http
  9. this.qrCodeDia = true
  10. },
  11. // 判断浏览器类型
  12. myBrowser() {
  13. var userAgent = navigator.userAgent // 取得浏览器的userAgent字符串
  14. var isOpera = userAgent.indexOf('Opera') > -1
  15. if (isOpera) {
  16. return 'Opera'
  17. }
  18. if (userAgent.indexOf('Firefox') > -1) {
  19. return 'FF'
  20. }
  21. if (userAgent.indexOf('Chrome') > -1) {
  22. return 'Chrome'
  23. }
  24. if (userAgent.indexOf('Safari') > -1) {
  25. return 'Safari'
  26. }
  27. if (userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 && !isOpera) {
  28. return 'IE'
  29. }
  30. if (userAgent.indexOf('Trident') > -1) {
  31. return 'Edge'
  32. }
  33. },
  34. // ②IE浏览器图片保存
  35. SaveAs5(imgURL) {
  36. var bstr = atob(imgURL.split(',')[1])
  37. var n = bstr.length
  38. var u8arr = new Uint8Array(n)
  39. while (n--) {
  40. u8arr[n] = bstr.charCodeAt(n)
  41. }
  42. var blob = new Blob([u8arr])
  43. window.navigator.msSaveOrOpenBlob(blob, '小区二维码.jpg')
  44. },
  45. /**
  46. * @author liujie22
  47. * @desc 下载二维码
  48. */
  49. downloadImg() {
  50. var oQrcode = document.querySelector('#qrcode img')
  51. var url = oQrcode.src
  52. if (this.myBrowser() === 'IE' || this.myBrowser() === 'Edge') {
  53. // IE (浏览器)
  54. this.SaveAs5(url)
  55. } else {
  56. //! IE (非IE)
  57. var a = document.createElement('a') // 创建一个a节点插入的document
  58. var event = new MouseEvent('click') // 模拟鼠标click点击事件
  59. a.download = '小区二维码' // 设置a节点的download属性值
  60. a.href = url // 将图片的src赋值给a节点的href
  61. a.dispatchEvent(event)
  62. }
  63. },
  64. 复制代码

2、h5端手机照片上传与拍照相关知识

上传与拍照方法

  1. <template>
  2. <div ref="imageUploadContainer" class="imageUploadContainer">
  3. <div
  4. v-for="(item, index) in filePreviewList"
  5. :key="index"
  6. class="uploadPreviewItem previewItem"
  7. >
  8. <img
  9. class="prevImg"
  10. :style="{ width: '95px', height: '133px' }"
  11. :src="item"
  12. @click="imgPreview(index)"
  13. />
  14. <i class="van-icon van-icon-clear deleteImgIcon" @click="deleteImg(index)"></i>
  15. </div>
  16. <div
  17. v-if="max === -1 || fileList.length < max"
  18. ref="uploadBtn"
  19. class="uploadBtn previewItem"
  20. @click="onAddFileBtnClick"
  21. >
  22. <i class="van-icon van-icon-plus uploadeIcon"></i>
  23. <input type="file" accept="image/jpg" @change="fileChange" />
  24. </div>
  25. </div>
  26. </template>
  27. 复制代码

图片上传及压缩方法

  1. // 文件选择变化事件
  2. // 文件名不带后缀的文件上传会失败TODO:
  3. async fileChange(e) {
  4. // 数量检查
  5. if (this.max && this.fileList.length >= 6) {
  6. Toast('超过数量限制')
  7. return false
  8. }
  9. let file = e.target.files[0]
  10. // 取消选择的话file对象不存在
  11. if (!file) {
  12. return false
  13. }
  14. const that = this
  15. // 图片大小检查
  16. const ms = file.size / 1024
  17. if (this.size && ms > this.size) {
  18. that.photoCompress(
  19. file,
  20. {
  21. width: 400,
  22. height: 600,
  23. // 调用压缩图片方法
  24. quality: 0.9
  25. },
  26. async function(base64Codes) {
  27. let bl = that.base64UrlToBlob(base64Codes)
  28. // 图片大小检查
  29. const mss = bl.size / 1024
  30. if (that.size && mss > that.size) {
  31. Toast(`超过${that.size}KB的大小限制`)
  32. } else if (mss < 10) {
  33. Toast(`不能小于10KB的大小限制`)
  34. } else {
  35. if (that.base64) {
  36. bl = await that.toDataURL(bl)
  37. }
  38. that.trigger(bl)
  39. }
  40. }
  41. )
  42. } else if (ms < 10) {
  43. Toast(`不能小于10KB的大小限制`)
  44. } else {
  45. if (this.base64) {
  46. file = await this.toDataURL(file)
  47. }
  48. this.trigger(file)
  49. }
  50. },
  51. 复制代码
  1. /*
  2. *压缩图片
  3. *file:文件(类型是图片格式),
  4. *obj:文件压缩后对象width, height, quality(0-1)
  5. *callback:容器或者回调函数
  6. */
  7. photoCompress(file, obj, callback) {
  8. const that = this
  9. const ready = new FileReader() /* 开始读取指定File对象中的内容. 读取操作完成时,返回一个URL格式的字符串. */
  10. ready.readAsDataURL(file)
  11. ready.onload = function() {
  12. const re = this.result
  13. that.canvasDataURL(re, obj, callback) // 开始压缩
  14. }
  15. },
  16. 复制代码
  1. /* 利用canvas数据化图片进行压缩 */
  2. /* 图片转base64 */
  3. canvasDataURL(path, obj, callback) {
  4. const img = new Image()
  5. img.src = path
  6. img.onload = function() {
  7. const that = this // 指到img // 默认按比例压缩
  8. let w = that.width
  9. let h = that.height
  10. const scale = w / h
  11. w = obj.width || w
  12. h = obj.height || w / scale
  13. const quality = obj.quality // 默认图片质量为0.7 // 生成canvas
  14. const canvas = document.createElement('canvas')
  15. const ctx = canvas.getContext('2d') // 创建属性节点
  16. const anw = document.createAttribute('width')
  17. anw.nodeValue = w
  18. const anh = document.createAttribute('height')
  19. anh.nodeValue = h
  20. canvas.setAttributeNode(anw)
  21. canvas.setAttributeNode(anh)
  22. ctx.drawImage(that, 0, 0, w, h) // 图像质量
  23. // quality值越小,所绘制出的图像越模糊
  24. const base64 = canvas.toDataURL('image/jpeg', quality) // 回调函数返回base64的值
  25. callback(base64)
  26. }
  27. },
  28. 复制代码
  1. /**
  2. * base64 转 Blob 格式 和file格式
  3. */
  4. base64UrlToBlob(urlData) {
  5. const arr = urlData.split(',')
  6. const mime = arr[0].match(/:(.*?);/)[1] // 去掉url的头,并转化为byte
  7. const bstr = atob(arr[1]) // 处理异常,将ascii码小于0的转换为大于0
  8. let n = bstr.length
  9. const u8arr = new Uint8Array(n)
  10. while (n--) {
  11. u8arr[n] = bstr.charCodeAt(n)
  12. } // 转blob // return new Blob([u8arr], {type: mime})
  13. const filename = Date.parse(new Date()) + '.jpg' // 转file
  14. return new File([u8arr], filename, { type: mime })
  15. },
  16. 复制代码
  1. /**
  2. * @Desc: 二进制数据转base65
  3. */
  4. toDataURL(blob) {
  5. return new Promise((resolve, reject) => {
  6. const a = new FileReader()
  7. a.onload = e => {
  8. resolve(e.target.result)
  9. }
  10. a.readAsDataURL(blob)
  11. })
  12. },
  13. 复制代码
  1. /**
  2. * @Desc: 触发事件,调用父组件方法
  3. */
  4. trigger(tar) {
  5. this.fileList.concat([tar])
  6. if (typeof tar === 'string') {
  7. this.$emit('afterRead', { base: tar })
  8. } else {
  9. this.$emit('afterRead', { base: tar })
  10. }
  11. },
  12. 复制代码

图片展示

  1. computed: {
  2. // 预览列表
  3. filePreviewList() {
  4. return this.fileList.map(item => {
  5. return typeof item === 'object' ? window.URL.createObjectURL(item) : item
  6. })
  7. }
  8. },