微信小程序中使用canvas如何實現對進行壓縮?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
微信小程序其實自帶一個圖片壓縮的API wx.compressImage,但是這玩意目前感受就是個垃圾。IOS大多數情況下據說還可以,安卓有的時候降低質量壓縮后體積反而變大,而且沒辦法控制其壓縮至具體指定的大小,壓縮后多大看天意。所以需要使用畫布去自己實現一個圖片壓縮方法。
簡單來講原理就是:找個不顯示在頁面上的畫布畫上去,再取出,如果體積還是太大,縮小尺寸后再畫,再取,遞歸下去,直到體積滿足要求。(所以限制的越小,圖片越大,壓縮越久,遞歸次數越多)
第一步:新建一個zipPic.js文件(名字你開心就好),里面的代碼如下
//通過canvas將圖片壓縮至指定大小
//判斷圖片大小是否滿足需求,limitSize的單位是kb
function imageSizeIsLessLimitSize(imagePath,limitSize,lessCallback,moreCallback){
//獲取文件信息
wx.getFileInfo({
filePath:imagePath,
success:(res)=>{
console.log("壓縮前圖片大小",res.size/1024,'kb');
//如果圖片太大了走moreCallback
if(res.size>1024*limitSize){
moreCallback()
}
//圖片滿足要求了走lessCallback
else{
lessCallback()
}
}
})
}
//將圖片畫在畫布上并獲取畫好之后的圖片的路徑
function getCanvasImage(canvasId,imagePath,imageW,imageH,getImgSuccess){
//創建畫布內容
const ctx=wx.createCanvasContext(canvasId);
//圖片畫上去,imageW和imageH是畫上去的尺寸,圖像和畫布間隔都是0
ctx.drawImage(imagePath,0,0,imageW,imageH);
//這里一定要加定時器,給足夠的時間去畫(所以每次遞歸最少要耗時200ms,多次遞歸很耗時?。?
ctx.draw(false,setTimeout(function(){
wx.canvasToTempFilePath({
canvasId:canvasId,
x:0,
y:0,
width:imageW,
height:imageH,
quality:1, //最高質量,只通過尺寸放縮去壓縮,畫的時候都按最高質量來畫
success:(res)=>{
getImgSuccess(res.tempFilePath);
}
})
},200));
}
//主函數,默認限制大小1024kb即1mb,drawWidth是繪畫區域的大小
//初始值傳入為畫布自身的邊長(我們這是一個正方形的畫布)
function getLessLimitSizeImage(canvasId,imagePath,limitSize=1024,drawWidth,callback){
//判斷圖片尺寸是否滿足要求
imageSizeIsLessLimitSize(imagePath,limitSize,
(lessRes)=>{
//滿足要求走callback,將壓縮后的文件路徑返回
callback(imagePath);
},
(moreRes)=>{
//不滿足要求需要壓縮的時候
wx.getImageInfo({
src:imagePath,
success:(imageInfo)=>{
let maxSide=Math.max(imageInfo.width,imageInfo.height);
let windowW=drawWidth;
let scale=1;
/*
這里的目的是當繪畫區域縮小的比圖片自身尺寸還要小的時候
取圖片長寬的最大值,然后和當前繪畫區域計算出需要放縮的比例
然后再畫經過放縮后的尺寸,保證畫出的一定是一個完整的圖片。由于每次遞歸繪畫區域都會縮小,
所以不用擔心scale永遠都是1繪畫尺寸永遠不變的情況,只要不滿足壓縮后體積的要求
就會縮小繪畫區域,早晚會有繪畫區域小于圖片尺寸的情況發生
*/
if(maxSide>windowW){
scale=windowW/maxSide;
}
//trunc是去掉小數
let imageW=Math.trunc(imageInfo.width*scale);
let imageH=Math.trunc(imageInfo.height*scale);
console.log('調用壓縮',imageW,imageH);
//圖片在規定繪畫區域上畫并獲取新的圖片的path
getCanvasImage(canvasId,imagePath,imageW,imageH,
(pressImgPath)=>{
/*
再去檢查是否滿足要求,始終縮小繪畫區域,讓圖片適配繪畫區域
這里乘以0.95是必須的,如果不縮小繪畫區域,會出現尺寸比繪畫區域小,
而體積比要求壓縮體積大的情況出現,就會無窮遞歸下去,因為scale的值永遠是1
但0.95不是固定的,你可以根據需要自己改,0到1之間,越小則繪畫區域縮小的越快
但不建議取得太小,繪畫區域縮小的太快,壓出來的將總是很糊的
*/
getLessLimitSizeImage(canvasId,pressImgPath,limitSize,drawWidth*0.95,callback);
}
)
}
})
}
)
}
export default getLessLimitSizeImage好的接下來是使用的方法:
在你想壓縮圖片的js代碼所對應的頁面中。先放置一個用戶看不見的畫布。
(就是如果我想在index.js中chooseImage再壓縮,就需要你在index.html中加上下面的html代碼)
<!--用于圖片壓縮的canvas畫布,不在頁面中展示,且id固定不可變--> <canvas canvas-id="zipCanvas" ></canvas> <!--畫布結束-->
其中cw的值我個人建議選擇用戶屏幕的寬度,如下,在page({…})的data中添加
//畫板邊長默認是屏幕寬度,正方形畫布 cw:wx.getSystemInfoSync().windowWidth,
個人建議畫布和繪畫區域都是正方形的,畢竟你也不知道要壓縮的圖片是橫向的還是縱向的。
然后,引入,不解釋
import getLessLimitSizeImage from '../../utils/zipPic'
在js代碼中:
wx.chooseImage({
count:1, //只傳一張
sizeType:'original', //原圖質量好,然后通過canvas壓縮,縮略圖壓縮就太糊了
sourceType: ['album', 'camera'], // 來源是相冊和相機
success:(res)=>{
let canvasId='zipCanvas' //注意這里的id和你在頁面中寫的html代碼的canvas的id要一致
let imagePath=res.tempFilePaths[0];//原圖的路徑
let limitSize=2048;//大小限制2048kb
let drawWidth=wx.getSystemInfoSync().windowWidth;//初始繪畫區域是畫布自身的寬度也就是屏幕寬度
wx.showLoading({title:'圖片壓縮中...',mask:true}) //不需要你可以刪掉
getLessLimitSizeImage(canvasId,imagePath,limitSize,drawWidth,(resPath)=>{
wx.hideLoading(); //不需要你可以刪掉
//resPath就是壓縮后圖片的路徑,然后想做什么都隨你
})
}
})補充:
看完上述內容,你們掌握微信小程序中使用canvas如何實現對進行壓縮的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。