• vant-基于van-uploader封装的文件上传图片压缩组件


    1、API说明

    属性名属性说明默认值
    valuev-model 绑定的上传图片列表
    compressSwitch是否开启图片压缩false

    quality

    图片压缩质量【0-1】0.1

    threshold

    图片压缩阈值(图片大于等于该阈值才进行压缩)

    500KB

    maxCount

    图片上传数量限制1

    2、调用

    1. <template>
    2. <div class="comp-ship">
    3. <compress-uploader v-model="fileList" :compressSwitch="true" :quality="0.5" :maxCount="3" />
    4. div>
    5. template>
    6. <script>
    7. import compressUploader from './components/compress-uploader'
    8. export default {
    9. name: 'CompShip',
    10. data () {
    11. return {
    12. fileList: [],
    13. }
    14. },
    15. components: {
    16. compressUploader
    17. }
    18. }
    19. script>
    20. <style lang="scss" scoped>
    21. style>

    2、核心代码

    1. <template>
    2. <van-uploader :fileList="fileList" :after-read="afterRead"
    3. multiple :max-count="maxCount" v-bind="$attrs" v-on="$listeners" />
    4. template>
    5. <script>
    6. export default {
    7. name: 'compress-uploader',
    8. props: {
    9. value: Array,
    10. quality: {
    11. type: Number,
    12. default: 0.1
    13. },
    14. compressSwitch: {
    15. type: Boolean,
    16. default: false
    17. },
    18. threshold: {
    19. type: Number,
    20. default: 500
    21. },
    22. maxCount: {
    23. type: Number,
    24. default: 1
    25. }
    26. },
    27. computed: {
    28. fileList: {
    29. get () {
    30. return this.value
    31. },
    32. set (n) {
    33. this.$emit('input', n)
    34. }
    35. }
    36. },
    37. methods: {
    38. afterRead (file, detail) {
    39. file.status = 'uploading'
    40. file.message = '上传中...'
    41. this.imgPreview(file, detail.index)
    42. return true
    43. },
    44. // 处理图片
    45. async imgPreview (myFile, index) {
    46. const file = myFile.file
    47. if (!file || !window.FileReader) { // 看支持不支持FileReader
    48. return
    49. }
    50. const size = file.size / 1024
    51. console.log(`图片大小 ===> ${size}kb`)
    52. console.log('图片压缩:', this.compressSwitch ? '开' : '关')
    53. console.log('图片压缩阈值:', this.threshold + 'kb')
    54. console.log('图片压缩降帧值:', this.quality)
    55. if (/^image/.test(file.type) && size >= this.threshold && this.compressSwitch) {
    56. const img = new Image()
    57. img.src = await this.getBase64(file) // 将图片将转成base64格式
    58. img.onload = () => {
    59. const data = this.compress(img, file.name, file.type)
    60. console.log(`压缩后 ===> ${data.fileData.size / 1024}kb`)
    61. this.fileList[index] = {
    62. content: data.base64Data,
    63. file: data.fileData
    64. }
    65. myFile.status = 'done'
    66. }
    67. } else {
    68. myFile.status = 'done'
    69. }
    70. },
    71. // 压缩图片
    72. compress (img, name, type) {
    73. const canvas = document.createElement('canvas')
    74. const ctx = canvas.getContext('2d')
    75. // 瓦片canvas
    76. const tCanvas = document.createElement('canvas')
    77. const tctx = tCanvas.getContext('2d')
    78. let width = img.width
    79. let height = img.height
    80. // 如果图片大于四百万像素,计算压缩比并将大小压至400万以下
    81. let ratio
    82. if ((ratio = (width * height) / 4000000) > 1) {
    83. ratio = Math.sqrt(ratio)
    84. width /= ratio
    85. height /= ratio
    86. } else {
    87. ratio = 1
    88. }
    89. canvas.width = width
    90. canvas.height = height
    91. // 铺底色
    92. ctx.fillStyle = '#fff'
    93. ctx.fillRect(0, 0, canvas.width, canvas.height)
    94. // 如果图片像素大于100万则使用瓦片绘制
    95. let count
    96. if ((count = (width * height) / 1000000) > 1) {
    97. count = ~~(Math.sqrt(count) + 1) // 计算要分成多少块瓦片
    98. // 计算每块瓦片的宽和高
    99. const nw = ~~(width / count)
    100. const nh = ~~(height / count)
    101. tCanvas.width = nw
    102. tCanvas.height = nh
    103. for (let i = 0; i < count; i++) {
    104. for (let j = 0; j < count; j++) {
    105. tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh)
    106. ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh)
    107. }
    108. }
    109. } else {
    110. ctx.drawImage(img, 0, 0, width, height)
    111. }
    112. // 进行压缩
    113. const ndata = canvas.toDataURL('image/jpeg', this.quality)
    114. tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0
    115. return { base64Data: ndata, fileData: this.dataURLtoFile(ndata, name, type) }
    116. },
    117. // 获取图片base64格式
    118. getBase64 (data) {
    119. return new Promise((resolve, reject) => {
    120. const fileReader = new FileReader()
    121. fileReader.onload = (e) => {
    122. resolve(e.target.result)
    123. }
    124. fileReader.readAsDataURL(data)
    125. fileReader.onerror = () => {
    126. reject(new Error('文件流异常'))
    127. }
    128. })
    129. },
    130. // 将base64转换为文件
    131. dataURLtoFile (dataurl, name, type) {
    132. name = name || '图片'
    133. type = type || 'jpg'
    134. const arr = dataurl.split(',')
    135. const bstr = atob(arr[1])
    136. let n = bstr.length
    137. const u8arr = new Uint8Array(n)
    138. while (n--) {
    139. u8arr[n] = bstr.charCodeAt(n)
    140. }
    141. return new File([u8arr], name, {
    142. type: type
    143. })
    144. }
    145. }
    146. }
    147. script>
  • 相关阅读:
    cmake + gtest安装使用 C++单元测试 gcov locv代码覆盖率
    C++标准模板库(STL)-list介绍
    OpenCV 10(图像轮廓)
    【单片机基础】单片机中断和定时
    uniapp小程序与webview通信(二)
    Kibana 中的身份验证-单点登录实现必读
    Atomic原子类详解
    化妆品展示网页设计作业 静态HTML化妆品网站 DW美妆网站模板下载 大学生简单网页作品代码 个人网页制作 学生个人网页设计作业
    Unity2D-怪物AI启发式寻路算法(多目标,任意怪物大小,攻击范围)
    详述 MIMIC护理人员信息表(十五)
  • 原文地址:https://blog.csdn.net/qq_40007317/article/details/127882274