微信小程序開發(fā)指南之圖片壓縮解決方案
前言:
由于公司業(yè)務(wù)拓展,急需基于uniapp生成支付寶小程序。之前已經(jīng)成功將微信小程序和H5融合成一套碼,故得知此需求的時(shí)候,筆者信心十足,但是本著實(shí)踐出真知的想法,覺得還是得先調(diào)研一下uniapp在支付寶小程序的兼容性,并集成已有項(xiàng)目主體關(guān)鍵功能,為后續(xù)的技術(shù)調(diào)研方案做準(zhǔn)備。在調(diào)研過程中,發(fā)現(xiàn)之前封裝好的圖片壓縮方法在支付寶小程序上無法正常使用,重新閱讀了官方文檔后,又雙更新了項(xiàng)目的圖片壓縮方法的使用流程。
問題:現(xiàn)有的壓縮方案支付寶小程序不生效
之前封裝好的壓縮方案,原理是使用canvas現(xiàn)實(shí)的,但是在支付寶小程序端不生效,canvas相關(guān)的api存在但是不可用。
解決方案:
查閱文檔后,給canvas添加了id區(qū)分支付寶小程序,可兼容之。
以下是官方文檔原文
uni.createCanvasContext(canvasId, this)#定義
畫布表示,傳入定義在 <canvas/> 的 canvas-id或id(支付寶小程序是id、其他平臺(tái)是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()
}
}
})
} // 主調(diào)用方法
/**
* 獲取小于限制大小的Image, limitSize默認(rèn)為1M,遞歸調(diào)用。
*/
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) //畫板的寬高默認(rèn)是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('調(diào)用壓縮', 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調(diào)用并上傳服務(wù)器:
<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('請(qǐng)至少選擇一張圖片')
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)
},
// 打開相冊(cè)
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('上傳超時(shí),請(qǐng)稍后再試')
} else {
this.$util.showModal('圖片上傳失敗,請(qǐng)稍后再試')
}
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>附:微信小程序圖片壓縮(支持多張圖)
原理上是使用canvas實(shí)現(xiàn)的,小于100k的圖片不做壓縮。
var {getCanvasImg} = require('../../common/img-compression.js'); // 在page上面按需引入
然后在wx.chooseImage接口成功回調(diào)中調(diào)用(使用tempFiles字段,因?yàn)樗藞D片大小)
let tempFiles = result.tempFiles; let i = 0; var arr = []; // par1:this; par2:圖片壓縮數(shù)組,含size字段;par3:遞增值,默認(rèn)先傳入0; par4:接收壓縮結(jié)果數(shù)組; par5:設(shè)置畫布大小回調(diào)函數(shù); par6:設(shè)置壓縮后的圖片數(shù)組 getCanvasImg(that, tempFiles, i, that.data.quality, arr, that.setCanvasSize, that.setCompImg);
在定義兩個(gè)回調(diào)函數(shù),用于設(shè)置畫布大小和接收壓縮結(jié)果
// 設(shè)置畫布大小
setCanvasSize(cWidth, cHeight){
this.setData({
cWidth,
cHeight
});
},
// 接收壓縮結(jié)果
setCompImg(imagePath){
this.setData({
imagePath // 壓縮結(jié)果
})
},
至此使用步驟已介紹完畢
小結(jié):
以上就是筆者分享的圖片壓縮上傳的方法封裝及使用啦,完美兼容支付寶小程序,微信小程序及H5三端。
到此這篇關(guān)于微信小程序開發(fā)指南之圖片壓縮解決方案的文章就介紹到這了,更多相關(guān)微信小程序圖片壓縮內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
2007/12/23更新創(chuàng)意無限,簡單實(shí)用(javascript log)
在javascript開發(fā)過程中,如果總是使用alert的方式調(diào)試程序,在某些簡單的程序中是可行的. 但是在通常的項(xiàng)目很復(fù)雜,這種方式已經(jīng)很難滿足,企業(yè)級(jí)開發(fā)的需要。2007-12-12
JavaScript如何使用Promise實(shí)現(xiàn)分批處理接口請(qǐng)求
當(dāng)我們?cè)陂_發(fā)時(shí)遇到需要同時(shí)發(fā)起百條接口請(qǐng)求怎么辦呢,本文主要來和大家介紹一下JavaScript如何使用Promise實(shí)現(xiàn)分批處理接口請(qǐng)求,需要的可以參考下2024-03-03
JS及JQuery對(duì)Html內(nèi)容編碼,Html轉(zhuǎn)義
本文主要介紹了JS及JQuery對(duì)Html內(nèi)容編碼,Html轉(zhuǎn)義的方法。具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-02-02
js實(shí)現(xiàn)連續(xù)英文字符自動(dòng)換行兼容ie6 ie7和firefox
英文字符自動(dòng)換行,通過js腳本截?cái)嘧址?此方法通用ie6,ie7,firefox,使用CSS控制強(qiáng)制換行實(shí)現(xiàn)不了的朋友可以嘗試下2013-09-09
基于bootstrap-datetimepicker.js不支持IE8的快速解決方法
下面小編就為大家?guī)硪黄赽ootstrap-datetimepicker.js不支持IE8的快速解決方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11

