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

目录


前言:

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

问题:现有的压缩方案不生效

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

解决方案:

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

以下是官方文档原文

uni.createCanvasContext(canvasId, this)

定义

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

核心代码展示:

1,封装公用工具类compressImage.js

  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="item.path"
  11. @click="viewImage(index)"></image>
  12. <image class="image-delete"
  13. :src="imgUrl + 'doctor/img_delete.png'"
  14. @tap.stop="deleteImage"
  15. :data-index="index"></image>
  16. </view>
  17. <view v-if="fileList.length < 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 './compressImage.js'
  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三端。希望对大家有所帮助。如有错误希望各位大神多多指教。

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发