目录
前言:
定制开发由于公司业务拓展,定制开发急需基于生成支付宝小程序。定制开发之前已经成功将微信小程序和H5定制开发融合成一套码,定制开发故得知此需求的时候,定制开发笔者信心十足,定制开发但是本着实践出真知的想法,觉得还是得先调研一下uniapp在支付宝小程序的兼容性,并集成已有项目主体关键功能,为后续的技术调研方案做准备。在调研过程中,发现之前封装好的图片压缩方法在支付宝小程序上无法正常使用,重新阅读了官方文档后,又双更新了项目的图片压缩方法的使用流程。
问题:现有的压缩方案不生效
之前封装好的压缩方案,原理是使用canvas现实的,但是在支付宝小程序端不生效,canvas相关的api存在但是不可用。
解决方案:
查阅文档后,给canvas添加了id区分支付宝小程序,可兼容之。
以下是官方文档原文
uni.createCanvasContext(canvasId, this)
定义
画布表示,传入定义在
<canvas/>
的 canvas-id或id(支付宝小程序是id、其他平台是canvas-id)
核心代码展示:
1,封装公用工具类compressImage.js
- /**
- * 给的文件资源是否小于LimitSize (M), 小于走lessCallBack, 大于走moreCallBack
- */
- export function imageSizeIsLessLimitSize(imagePath, limitSize, lessCallBack, moreCallBack) {
- uni.getFileInfo({
- filePath: imagePath,
-
- success(res) {
- console.log('压缩前图片大小:', res.size / 1024, 'kb')
-
- if (res.size > 1024 * 1024 * limitSize) {
- moreCallBack()
- } else {
- lessCallBack()
- }
- }
- })
- } // 主调用方法
-
- /**
- * 获取小于限制大小的Image, limitSize默认为1M,递归调用。
- */
-
- export function getLessLimitSizeImage(canvasId, imagePath, limitSize = 1, drawWidth, callBack) {
- imageSizeIsLessLimitSize(
- imagePath,
- limitSize,
- (lessRes) => {
- callBack(imagePath)
- },
- (moreRes) => {
- uni.getImageInfo({
- src: imagePath,
- success: function(imageInfo) {
- var maxSide = Math.max(imageInfo.width, imageInfo.height) //画板的宽高默认是windowWidth
-
- var windowW = drawWidth
- var scale = 1
-
- if (maxSide > windowW) {
- scale = windowW / maxSide
- }
-
- var imageW = Math.floor(imageInfo.width * scale)
- var imageH = Math.floor(imageInfo.height * scale)
- console.log('调用压缩', imageW, imageH)
- getCanvasImage(canvasId, imagePath, imageW, imageH, (pressImgPath) => {
- getLessLimitSizeImage(canvasId, pressImgPath, limitSize, drawWidth * 0.7, callBack)
- })
- }
- })
- }
- )
- }
- /**
- * 获取画布图片
- */
-
- export function getCanvasImage(canvasId, imagePath, imageW, imageH, getImgsuccess) {
- const ctx = uni.createCanvasContext(canvasId)
- ctx.drawImage(imagePath, 0, 0, imageW, imageH)
- ctx.draw(false, () => {
- uni.canvasToTempFilePath({
- canvasId: canvasId,
- x: 0,
- y: 0,
- width: imageW,
- height: imageH,
- quality: 1,
-
- success(res) {
- getImgsuccess(res.tempFilePath)
- }
- })
- })
- }
- export default {
- getLessLimitSizeImage,
- imageSizeIsLessLimitSize,
- getCanvasImage
- }
2,html调用并上传服务器:
- <template>
- <view class="upload-page">
- <view class="upload-tips">您最多可上传{{maxCount}}张图片</view>
- <view class="image-list">
- <view v-for="(item, index) in fileList"
- :key="index"
- class="image-item">
- <image class="image"
- mode="aspectFit"
- :src="item.path"
- @click="viewImage(index)"></image>
- <image class="image-delete"
- :src="imgUrl + 'doctor/img_delete.png'"
- @tap.stop="deleteImage"
- :data-index="index"></image>
- </view>
- <view v-if="fileList.length < maxCount"
- class="image-item"
- @tap="openAlbum">
- <image class="image"
- :src="imgUrl + 'doctor/img_add.png'"></image>
- </view>
- </view>
- <view class="upload-btn"
- @tap="confirmUpload">确定</view>
-
- <canvas canvas-id="pressCanvas"
- id="pressCanvas"
- class="press-canvas"></canvas>
- </view>
- </template>
-
- <script>
- import { getLessLimitSizeImage } from './compressImage.js'
-
-
- export default {
- data() {
- return {
- imgUrl: process.env.VUE_APP_RESOURCE_URL,
- page: {
- json: {}
- },
- type: '',
- fileList: [],
- maxCount: 9
- }
- },
-
- components: {},
- props: {},
-
- onLoad(options) {
- this.type = options.type
- this.page.json = options
- },
-
- methods: {
- confirmUpload() {
- if (this.fileList.length === 0) {
- this.$util.showToast('请至少选择一张图片')
- return false
- }
- this.$Router.back()
- uni.$emit(this.page.json.emit, this.fileList)
- },
-
- // 查看图片
- viewImage(index) {
- let copyData = [],
- data = [].concat(this.fileList)
- data.forEach((v) => {
- copyData.push(v.path)
- })
- uni.previewImage({
- current: copyData[index],
- urls: copyData
- })
- },
-
- // 删除图片
- deleteImage(e) {
- let { index } = e.currentTarget.dataset
- this.fileList.splice(index, 1)
- },
-
- // 打开相册
- openAlbum() {
- let length = this.maxCount - this.fileList.length
- uni.chooseImage({
- count: length,
- sizeType: ['original', 'compressed'],
- sourceType: ['album', 'camera'],
- success: (res) => {
- this.upLoadImgs(res.tempFilePaths, this.type)
- }
- })
- },
-
- // 上传多张图片
- upLoadImgs(files, type) {
- uni.showLoading()
- let promises = files.map((item) => {
- return this.uploadImg(item, type)
- })
- Promise.all(promises)
- .then((datas) => {
- // 所有上传完成后
- this.fileList = datas.length > 0 && this.fileList.concat(datas)
-
- uni.hideLoading()
- })
- .catch(() => {
- uni.hideLoading()
- })
- },
-
- // 上传图片
- uploadImg(file, type) {
- return new Promise((resolve, reject) => {
- getLessLimitSizeImage('pressCanvas', file, 1, 750, (imagePath) => {
- /* #ifdef H5 */
- let devicetype = 'h5'
- /* #endif */
- /* #ifdef MP-WEIXIN */
- let devicetype = 'applet'
- /* #endif */
-
- /* #ifdef MP-ALIPAY */
- let devicetype = 'alipay'
- /* #endif */
-
- uni.uploadFile({
- url: process.env.VUE_APP_API_URL + 'client/v1/file/images',
- header: {
- 'access-token': this.$store.state.user.accessToken,
- version: process.env.VUE_APP_VERSION,
- 'version-code': process.env.VUE_APP_VERSION_CODE,
- devicetype: devicetype
- },
- fileType: 'image',
- filePath: imagePath,
- name: 'file',
- formData: {
- source: 'inquiryApply',
- type: ''
- },
- success: (res) => {
- let image = JSON.parse(res.data)
- console.log('uploadFile success:', image)
-
- if (image.code === 200) {
- resolve(image.data[0])
- } else {
- this.$util.showModal(image.msg || '图片上传失败')
- reject(image)
- }
- },
- fail: (err) => {
- console.log('uploadFile fail:', JSON.stringify(err || {}))
-
- if (err.hasOwnProperty('errMsg') && err.errMsg.indexOf('timeout') > 0) {
- this.$util.showModal('上传超时,请稍后再试')
- } else {
- this.$util.showModal('图片上传失败,请稍后再试')
- }
-
- reject(err)
- },
- complete: () => {}
- })
- })
- })
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .upload-page {
- position: relative;
- width: 750rpx;
- height: 100vh;
- background-color: #ffffff;
- }
-
- .upload-tips {
- width: 750rpx;
- height: 80rpx;
- background-color: #fffbe8;
- font-size: 28rpx;
- color: #ed6a0c;
- line-height: 80rpx;
- text-align: center;
- }
-
- .image-list {
- box-sizing: border-box;
- display: flex;
- flex-wrap: wrap;
- justify-content: flex-start;
- align-items: center;
- width: 750rpx;
- padding: 30rpx;
- }
-
- .image-item {
- position: relative;
- box-sizing: border-box;
- width: 210rpx;
- height: 210rpx;
- margin-right: 30rpx;
- margin-bottom: 30rpx;
- border: 1rpx solid #ebedf0;
- }
-
- .image-item:nth-child(3n) {
- margin-right: 0;
- }
-
- .image-item .image {
- width: 210rpx;
- height: 210rpx;
- }
-
- .image-item .image-delete {
- position: absolute;
- top: -30rpx;
- right: -30rpx;
- width: 40rpx;
- height: 40rpx;
- padding: 10rpx;
- }
-
- .upload-btn {
- position: fixed;
- bottom: 0;
- left: 0;
- width: 750rpx;
- height: 100rpx;
- background-color: $primary;
- font-size: 30rpx;
- color: #ffffff;
- line-height: 100rpx;
- text-align: center;
- }
-
- .press-canvas {
- position: absolute;
- top: -1000px;
- left: -1000px;
- background-color: gray;
- width: 750px;
- height: 750px;
- }
- </style>
小结:
以上就是笔者分享的上传的方法封装及使用啦,完美兼容支付宝小程序,微信小程序及H5三端。希望对大家有所帮助。如有错误希望各位大神多多指教。