微信小程序开发之图片压缩方案

时间:2024-10-22 08:59:54

目录

 前言:

问题:现有的压缩方案支付宝小程序不生效

解决方案:

(canvasId, this)

核心代码展示:

1,封装公用工具类

2,html调用并上传服务器:

小结:


前言:

由于公司业务拓展,急需基于uniapp生成支付宝小程序。之前已经成功将微信小程序和H5融合成一套码,故得知此需求的时候,笔者信心十足,但是本着实践出真知的想法,觉得还是得先调研一下uniapp在支付宝小程序的兼容性,并集成已有项目主体关键功能,为后续的技术调研方案做准备。在调研过程中,发现之前封装好的图片压缩方法在支付宝小程序上无法正常使用,重新阅读了官方文档后,又双更新了项目的图片压缩方法的使用流程。

问题:现有的压缩方案支付宝小程序不生效

之前封装好的压缩方案,原理是使用canvas现实的,但是在支付宝小程序端不生效,canvas相关的api存在但是不可用。

解决方案:

查阅文档后,给canvas添加了id区分支付宝小程序,可兼容之。

以下是官方文档原文

(canvasId, this)

#定义

画布表示,传入定义在 <canvas/> 的 canvas-id或id(支付宝小程序是id、其他平台是canvas-id)

核心代码展示:

1,封装公用工具类

  1. /**
  2. * 给的文件资源是否小于LimitSize (M), 小于走lessCallBack, 大于走moreCallBack
  3. */
  4. export function imageSizeIsLessLimitSize(imagePath, limitSize, lessCallBack, moreCallBack) {
  5. uni.getFileInfo({
  6. filePath: imagePath,
  7. success(res) {
  8. console.log('压缩前图片大小:', res.size / 1024, 'kb')
  9. if (res.size > 1024 * 1024 * limitSize) {
  10. moreCallBack()
  11. } else {
  12. lessCallBack()
  13. }
  14. }
  15. })
  16. } // 主调用方法
  17. /**
  18. * 获取小于限制大小的Image, limitSize默认为1M,递归调用。
  19. */
  20. export function getLessLimitSizeImage(canvasId, imagePath, limitSize = 1, drawWidth, callBack) {
  21. imageSizeIsLessLimitSize(
  22. imagePath,
  23. limitSize,
  24. (lessRes) => {
  25. callBack(imagePath)
  26. },
  27. (moreRes) => {
  28. uni.getImageInfo({
  29. src: imagePath,
  30. success: function(imageInfo) {
  31. var maxSide = Math.max(imageInfo.width, imageInfo.height) //画板的宽高默认是windowWidth
  32. var windowW = drawWidth
  33. var scale = 1
  34. if (maxSide > windowW) {
  35. scale = windowW / maxSide
  36. }
  37. var imageW = Math.floor(imageInfo.width * scale)
  38. var imageH = Math.floor(imageInfo.height * scale)
  39. console.log('调用压缩', imageW, imageH)
  40. getCanvasImage(canvasId, imagePath, imageW, imageH, (pressImgPath) => {
  41. getLessLimitSizeImage(canvasId, pressImgPath, limitSize, drawWidth * 0.7, callBack)
  42. })
  43. }
  44. })
  45. }
  46. )
  47. }
  48. /**
  49. * 获取画布图片
  50. */
  51. export function getCanvasImage(canvasId, imagePath, imageW, imageH, getImgsuccess) {
  52. const ctx = uni.createCanvasContext(canvasId)
  53. ctx.drawImage(imagePath, 0, 0, imageW, imageH)
  54. ctx.draw(false, () => {
  55. uni.canvasToTempFilePath({
  56. canvasId: canvasId,
  57. x: 0,
  58. y: 0,
  59. width: imageW,
  60. height: imageH,
  61. quality: 1,
  62. success(res) {
  63. getImgsuccess(res.tempFilePath)
  64. }
  65. })
  66. })
  67. }
  68. export default {
  69. getLessLimitSizeImage,
  70. imageSizeIsLessLimitSize,
  71. getCanvasImage
  72. }

2,html调用并上传服务器:

  1. <template>
  2. <view class="upload-page">
  3. <view class="upload-tips">您最多可上传{{maxCount}}张图片</view>
  4. <view class="image-list">
  5. <view v-for="(item, index) in fileList"
  6. :key="index"
  7. class="image-item">
  8. <image class="image"
  9. mode="aspectFit"
  10. :src=""
  11. @click="viewImage(index)"></image>
  12. <image class="image-delete"
  13. :src="imgUrl + 'doctor/img_delete.png'"
  14. @="deleteImage"
  15. :data-index="index"></image>
  16. </view>
  17. <view v-if=" < maxCount"
  18. class="image-item"
  19. @tap="openAlbum">
  20. <image class="image"
  21. :src="imgUrl + 'doctor/img_add.png'"></image>
  22. </view>
  23. </view>
  24. <view class="upload-btn"
  25. @tap="confirmUpload">确定</view>
  26. <canvas canvas-id="pressCanvas"
  27. id="pressCanvas"
  28. class="press-canvas"></canvas>
  29. </view>
  30. </template>
  31. <script>
  32. import { getLessLimitSizeImage } from './'
  33. export default {
  34. data() {
  35. return {
  36. imgUrl: process.env.VUE_APP_RESOURCE_URL,
  37. page: {
  38. json: {}
  39. },
  40. type: '',
  41. fileList: [],
  42. maxCount: 9
  43. }
  44. },
  45. components: {},
  46. props: {},
  47. onLoad(options) {
  48. this.type = options.type
  49. this.page.json = options
  50. },
  51. methods: {
  52. confirmUpload() {
  53. if (this.fileList.length === 0) {
  54. this.$util.showToast('请至少选择一张图片')
  55. return false
  56. }
  57. this.$Router.back()
  58. uni.$emit(this.page.json.emit, this.fileList)
  59. },
  60. // 查看图片
  61. viewImage(index) {
  62. let copyData = [],
  63. data = [].concat(this.fileList)
  64. data.forEach((v) => {
  65. copyData.push(v.path)
  66. })
  67. uni.previewImage({
  68. current: copyData[index],
  69. urls: copyData
  70. })
  71. },
  72. // 删除图片
  73. deleteImage(e) {
  74. let { index } = e.currentTarget.dataset
  75. this.fileList.splice(index, 1)
  76. },
  77. // 打开相册
  78. openAlbum() {
  79. let length = this.maxCount - this.fileList.length
  80. uni.chooseImage({
  81. count: length,
  82. sizeType: ['original', 'compressed'],
  83. sourceType: ['album', 'camera'],
  84. success: (res) => {
  85. this.upLoadImgs(res.tempFilePaths, this.type)
  86. }
  87. })
  88. },
  89. // 上传多张图片
  90. upLoadImgs(files, type) {
  91. uni.showLoading()
  92. let promises = files.map((item) => {
  93. return this.uploadImg(item, type)
  94. })
  95. Promise.all(promises)
  96. .then((datas) => {
  97. // 所有上传完成后
  98. this.fileList = datas.length > 0 && this.fileList.concat(datas)
  99. uni.hideLoading()
  100. })
  101. .catch(() => {
  102. uni.hideLoading()
  103. })
  104. },
  105. // 上传图片
  106. uploadImg(file, type) {
  107. return new Promise((resolve, reject) => {
  108. getLessLimitSizeImage('pressCanvas', file, 1, 750, (imagePath) => {
  109. /* #ifdef H5 */
  110. let devicetype = 'h5'
  111. /* #endif */
  112. /* #ifdef MP-WEIXIN */
  113. let devicetype = 'applet'
  114. /* #endif */
  115. /* #ifdef MP-ALIPAY */
  116. let devicetype = 'alipay'
  117. /* #endif */
  118. uni.uploadFile({
  119. url: process.env.VUE_APP_API_URL + 'client/v1/file/images',
  120. header: {
  121. 'access-token': this.$store.state.user.accessToken,
  122. version: process.env.VUE_APP_VERSION,
  123. 'version-code': process.env.VUE_APP_VERSION_CODE,
  124. devicetype: devicetype
  125. },
  126. fileType: 'image',
  127. filePath: imagePath,
  128. name: 'file',
  129. formData: {
  130. source: 'inquiryApply',
  131. type: ''
  132. },
  133. success: (res) => {
  134. let image = JSON.parse(res.data)
  135. console.log('uploadFile success:', image)
  136. if (image.code === 200) {
  137. resolve(image.data[0])
  138. } else {
  139. this.$util.showModal(image.msg || '图片上传失败')
  140. reject(image)
  141. }
  142. },
  143. fail: (err) => {
  144. console.log('uploadFile fail:', JSON.stringify(err || {}))
  145. if (err.hasOwnProperty('errMsg') && err.errMsg.indexOf('timeout') > 0) {
  146. this.$util.showModal('上传超时,请稍后再试')
  147. } else {
  148. this.$util.showModal('图片上传失败,请稍后再试')
  149. }
  150. reject(err)
  151. },
  152. complete: () => {}
  153. })
  154. })
  155. })
  156. }
  157. }
  158. }
  159. </script>
  160. <style lang="scss" scoped>
  161. .upload-page {
  162. position: relative;
  163. width: 750rpx;
  164. height: 100vh;
  165. background-color: #ffffff;
  166. }
  167. .upload-tips {
  168. width: 750rpx;
  169. height: 80rpx;
  170. background-color: #fffbe8;
  171. font-size: 28rpx;
  172. color: #ed6a0c;
  173. line-height: 80rpx;
  174. text-align: center;
  175. }
  176. .image-list {
  177. box-sizing: border-box;
  178. display: flex;
  179. flex-wrap: wrap;
  180. justify-content: flex-start;
  181. align-items: center;
  182. width: 750rpx;
  183. padding: 30rpx;
  184. }
  185. .image-item {
  186. position: relative;
  187. box-sizing: border-box;
  188. width: 210rpx;
  189. height: 210rpx;
  190. margin-right: 30rpx;
  191. margin-bottom: 30rpx;
  192. border: 1rpx solid #ebedf0;
  193. }
  194. .image-item:nth-child(3n) {
  195. margin-right: 0;
  196. }
  197. .image-item .image {
  198. width: 210rpx;
  199. height: 210rpx;
  200. }
  201. .image-item .image-delete {
  202. position: absolute;
  203. top: -30rpx;
  204. right: -30rpx;
  205. width: 40rpx;
  206. height: 40rpx;
  207. padding: 10rpx;
  208. }
  209. .upload-btn {
  210. position: fixed;
  211. bottom: 0;
  212. left: 0;
  213. width: 750rpx;
  214. height: 100rpx;
  215. background-color: $primary;
  216. font-size: 30rpx;
  217. color: #ffffff;
  218. line-height: 100rpx;
  219. text-align: center;
  220. }
  221. .press-canvas {
  222. position: absolute;
  223. top: -1000px;
  224. left: -1000px;
  225. background-color: gray;
  226. width: 750px;
  227. height: 750px;
  228. }
  229. </style>

小结:

以上就是笔者分享的图片压缩上传的方法封装及使用啦,完美兼容支付宝小程序,微信小程序及H5三端。希望对大家有所帮助。如有错误希望各位大神多多指教。