微信小程序開(kāi)發(fā)指南之圖片壓縮解決方案
前言:
由于公司業(yè)務(wù)拓展,急需基于uniapp生成支付寶小程序。之前已經(jīng)成功將微信小程序和H5融合成一套碼,故得知此需求的時(shí)候,筆者信心十足,但是本著實(shí)踐出真知的想法,覺(jué)得還是得先調(diào)研一下uniapp在支付寶小程序的兼容性,并集成已有項(xiàng)目主體關(guān)鍵功能,為后續(xù)的技術(shù)調(diào)研方案做準(zhǔn)備。在調(diào)研過(guò)程中,發(fā)現(xiàn)之前封裝好的圖片壓縮方法在支付寶小程序上無(wú)法正常使用,重新閱讀了官方文檔后,又雙更新了項(xiàng)目的圖片壓縮方法的使用流程。
問(wèn)題:現(xiàn)有的壓縮方案支付寶小程序不生效
之前封裝好的壓縮方案,原理是使用canvas現(xiàn)實(shí)的,但是在支付寶小程序端不生效,canvas相關(guān)的api存在但是不可用。
解決方案:
查閱文檔后,給canvas添加了id區(qū)分支付寶小程序,可兼容之。
以下是官方文檔原文
uni.createCanvasContext(canvasId, this)#定義
畫(huà)布表示,傳入定義在 <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) //畫(huà)板的寬高默認(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) }) } }) } ) } /** * 獲取畫(huà)布圖片 */ 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) }, // 打開(kāi)相冊(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è)置畫(huà)布大小回調(diào)函數(shù); par6:設(shè)置壓縮后的圖片數(shù)組 getCanvasImg(that, tempFiles, i, that.data.quality, arr, that.setCanvasSize, that.setCompImg);
在定義兩個(gè)回調(diào)函數(shù),用于設(shè)置畫(huà)布大小和接收壓縮結(jié)果
// 設(shè)置畫(huà)布大小 setCanvasSize(cWidth, cHeight){ this.setData({ cWidth, cHeight }); }, // 接收壓縮結(jié)果 setCompImg(imagePath){ this.setData({ imagePath // 壓縮結(jié)果 }) },
至此使用步驟已介紹完畢
小結(jié):
以上就是筆者分享的圖片壓縮上傳的方法封裝及使用啦,完美兼容支付寶小程序,微信小程序及H5三端。
到此這篇關(guān)于微信小程序開(kāi)發(fā)指南之圖片壓縮解決方案的文章就介紹到這了,更多相關(guān)微信小程序圖片壓縮內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)兩個(gè)select下拉框選項(xiàng)左移右移
這篇文章主要介紹了JavaScript實(shí)現(xiàn)兩個(gè)select下拉框選項(xiàng)左移右移功能,js實(shí)現(xiàn)下拉框元素互相移動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03JS實(shí)現(xiàn)json的序列化和反序列化功能示例
這篇文章主要介紹了JS實(shí)現(xiàn)json的序列化和反序列化功能,結(jié)合具體實(shí)例形式分析了javascript針對(duì)json的序列化與反序列化相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-06-06JavaScript實(shí)現(xiàn)滑動(dòng)門(mén)效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)滑動(dòng)門(mén)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-01-01js獲取異步函數(shù)數(shù)據(jù)的實(shí)現(xiàn)
本文主要介紹了js獲取異步函數(shù)數(shù)據(jù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02JavaScript基于遍歷操作實(shí)現(xiàn)對(duì)象深拷貝功能示例
這篇文章主要介紹了JavaScript基于遍歷操作實(shí)現(xiàn)對(duì)象深拷貝功能,涉及javascript元素遍歷與屬性操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-03-03JS長(zhǎng)整型精度問(wèn)題實(shí)例分析
這篇文章主要介紹了JS長(zhǎng)整型精度問(wèn)題,實(shí)例分析了Java項(xiàng)目結(jié)合前臺(tái)js腳本出現(xiàn)的長(zhǎng)整型精度問(wèn)題與相應(yīng)的解決方案,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-01-01JS中g(shù)etElementsByClassName與classList兼容性問(wèn)題解決方案分析
這篇文章主要介紹了JS中g(shù)etElementsByClassName與classList兼容性問(wèn)題解決方案,結(jié)合實(shí)例形式分析了getElementsByClassName與classList的使用方法、原理及兼容性問(wèn)題的處理技巧,需要的朋友可以參考下2019-08-08javascript實(shí)現(xiàn)的一個(gè)自定義長(zhǎng)度的文本自動(dòng)換行的函數(shù)。
javascript實(shí)現(xiàn)的一個(gè)自定義長(zhǎng)度的文本自動(dòng)換行的函數(shù)。...2007-08-08