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


    目录

     前言:

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

    解决方案:

    uni.createCanvasContext(canvasId, this)

    核心代码展示:

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

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

    小结:


    前言:

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

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

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

    解决方案:

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

    以下是官方文档原文

    uni.createCanvasContext(canvasId, this)

    #定义

    画布表示,传入定义在  的 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三端。希望对大家有所帮助。如有错误希望各位大神多多指教。

  • 相关阅读:
    【对当前现状的分析】如何做好学术汇报的PPT?
    个人笔记-ADC
    02-docker network
    虚拟机Ubuntu操作系统最基本终端命令(安装包+详细解释+详细演示)
    2678. 老人的数目 --力扣 --JAVA
    vmware安装MacOS以及flutter遇到的问题
    JVM【类加载与GC垃圾回收机制】
    Android硬件服务访问(3):编写JNI方法提供Java访问硬件服务接口
    MySQL导出数据为csv的方法(亲测)
    C++函数模板
  • 原文地址:https://blog.csdn.net/m0_61243965/article/details/126002755