小程式圖片裁剪功能簡易版,分享前裁剪
阿新 • • 發佈:2019-01-10
該檔案主要執行分享前的裁剪
微信後臺的download安全域名別忘記設定,否則上線後不能剪下
小程式內是圖片是HTTP的要想辦法換成https
一.介紹使用
1.基本使用
以商品詳情為例:
<template>
<view class="container">
<!-- n個佈局 -->
<view wx:if="{{cutData.imageInfor}}">
<canvas style="width:{{cutData.imageInfor.width}}px;height: {{cutData.imageInfor.height}}px;display:{{cutData.showCanvas ? 'block':'none'}};" canvas-id="cropper"></canvas>
<!-- 為了看裁剪效果,實際可以沒有此元素 -->
<!-- <image src="{{cutData.savedFilePath}}"></image> -->
</view>
</view>
</template>
<script>
import cut from '../../utils/cut';
export default class ProductDetail extends wepy.page {
// 分享事件,暫時沒有做回撥事件
onShareAppMessage() {
let info = wx.getStorageSync(USER_INFO);
return {
title: this.product.baseInfo.name,
imageUrl: this.cutData.savedFilePath,
path: "/pages/mine/white_page?pid=" + this.product.baseInfo.productId + "&source=" + info.userId,
success: function(res) {
// 轉發成功
console.log('轉發成功');
},
fail: function(res) {
// 轉發失敗
console.log('轉發失敗');
}
};
}
config = {
navigationBarTitleText: "商品詳情"
};
data = {
product: {},
cutData:{ // 分享剪下處理
imageInfor:null,
savedFilePath:'',
showCanvas:true, // 初始顯示canvas,若初始不顯示canvas會裁剪報錯
}
};
methods = {
// 分享事件,顯示分享按鈕
handleShare() {
console.log(1111);
wx.showShareMenu({
withShareTicket: true
});
},
};
// 頁面載入事件
onLoad(option) {
// 前面n個操作
this.getData();
}
async getData(pid , shop) {
// 前面n個操作
let res = await getProductDetail(params);
if (res.data.code == 200) {
this.product = res.data.data;
this.isError = false;
// 執行裁剪
this._myCut();
} else if(res.data.code == 500) {
// ...
} else {
this.isError = true;
}
this.$apply();
}
// 參見方法,每次onload都執行
_myCut() {
if (!this.product.headPics) {
return ;
}
cut.cut(this.product.headPics[0].imgUrl,'cropper'
,imageInfor => { // 得到待分享圖片的資訊
this.cutData.imageInfor = imageInfor;
this.$apply();
}
,savedFilePath => { // 獲取儲存到本地的圖片資訊
this.cutData.savedFilePath = savedFilePath;
// 將canvas隱藏,不影響頁面佈局
this.cutData.showCanvas = false;
this.$apply();
// 清除本地儲存的檔案列表,但是不包含本次生成的檔案
cut.clearSavedFileList(this.cutData.savedFilePath);
}
);
};
}
</script>
<style lang="less"></style>
2.注意
- 在_myCut函式中,得到本地儲存路徑後的回撥內應將canvas隱藏,防止被使用者看到
- 放canvas的view應該放在頁面最底部,防止初始出現的時候被使用者看到
- 在得到本地儲存路徑後的回撥內應將微信內儲存的其他savedFileList刪除,這裡如果自己存放了其他資源,可以選擇修改cut.js的clearSavedFileList方法.
- 之所以不在onShareAppMessage方法內之間裁剪(也就是使用者點選了分享或者轉發才裁剪),是因為onShareAppMessage方法要求返回一個物件,cut.js採用回撥實現,cut中的cut方法中回撥的值不能被onShareAppMessage拿到,所以放在了getData方法中
二.介紹實現
1.實現
cut.js
export default {
// 裁剪方法
cut(url,canvasId,imageInforCB,savedFilePathCB) {
let that = this;
const ctx = wx.createCanvasContext('cropper');
that._getImageInfor(url,ctx,canvasId,imageInforCB,savedFilePathCB);
},
// 刪除本地儲存資料
clearSavedFileList(currSavedFilePath) {
wx.getSavedFileList({
success: function(res) {
for (let i=0;i<res.fileList.length;i++) {
if (currSavedFilePath !== res.fileList[i].filePath) {
wx.removeSavedFile({
filePath: res.fileList[i].filePath,
complete: function(res) {
console.log('本地圖片刪除結束',res);
}
});
}
}
}
});
},
// 獲取圖片資訊
_getImageInfor(url,ctx,canvasId,imageInforCB,savedFilePathCB) {
let that = this;
wx.getImageInfo({
src: url,
success: function (imageInfor) {
console.log('getImageInfo2',imageInfor);
imageInforCB(imageInfor);
// 將圖畫到canvas上
that._drawImage(ctx,imageInfor,()=>{
that._getTempFilePath(canvasId,imageInfor,savedFilePathCB);
});
},
fail: function(res) {
console.log('getImageInfo fail',res);
},
complete:function(res) {
console.log('getImageInfo complete',res);
}
});
},
// 在canvas上畫圖
_drawImage(ctx,imageInfor,cb) {
ctx.drawImage(imageInfor.path,0,0,imageInfor.width,imageInfor.height);
ctx.draw(false,()=>{
console.log('繪製完成');
cb();
});
},
// 使用canvas剪裁,後獲取臨時本地路徑,
_getTempFilePath(canvasId,imageInfor,savedFilePathCB) {
let that = this;
let cutData = that._computedCutData(imageInfor);
console.log('cutData',cutData);
wx.canvasToTempFilePath({
x: cutData.x,
y: cutData.y,
width: imageInfor.width,
height: imageInfor.height,
destWidth: cutData.destWidth,
destHeight: cutData.destHeight,
canvasId: canvasId,
success: function(res) {
console.log('canvasToTempFilePath res',res);
that._saveImage(res.tempFilePath,savedFilePathCB);
},
fail: function(res) {
console.log('canvasToTempFilePath fail',res);
},
complete:function(res) {
console.log('canvasToTempFilePath complete',res);
}
});
},
// 將_getTempFilePath得到的臨時路徑儲存到本地
_saveImage(tempFilePath,savedFilePathCB) {
wx.saveFile({
tempFilePath: tempFilePath,
success: function (res) {
let savedFilePath = res.savedFilePath;
console.log('savedFilePath',res);
savedFilePathCB(savedFilePath);
},
fail:function() {
console.log('saveFile,fail');
},
complete:function() {
console.log('saveFile,complete');
}
});
},
// 計算裁剪資料,目前由長寬1:1裁成長寬比5:4的圖片,裁剪公式 (h-(w/5*4))/2
_computedCutData(imageInfor) {
let cutData = {
x:0, // canvas剪下左上角x座標
y:0, // canvas剪下左上角y座標
destWidth:0, // 圖片裁剪寬度
destHeight:0 // 圖片裁剪高度
};
let cutY = (imageInfor.height-(imageInfor.width/5*4))/2;
cutData.y = cutY;
cutData.x = 0;
cutData.destWidth = imageInfor.width;
cutData.destHeight = imageInfor.height - cutY*2;
return cutData;
}
}
2.注意
1.剪裁前要講圖片畫到canvas上,因為呼叫了canvas的canvasToTempFilePath方法
2.注意cut.js中clearSavedFileList方法是清除除了本次生成的圖片之外的所有微信小程式savedFileList,如不希望,可以修改此方法
3._computedCutData是計算裁剪資料,圖片將按照得到的結果裁剪,
4.本cut.js的_computedCutData裁剪尺寸是圖片寬度不變,高度上下各裁剪掉寬度的十分之一
5.wx.canvasToTempFilePath方法要在draw的回撥函式中執行才會正確得到結果
5.canvas的display:none;會觸發wx.canvasToTempFilePath失敗,因此應該首先canvas的display:block,當本地儲存路徑得到後再display:none即可
三.補充(2018/5/25)
上線之後發現圖片剪裁出現問題,當圖片寬高都超出2000的時候,不知道為何,小程式閃退,所以這裡做了修改,添加了如下方法:
此方法在_getImageInfor方法中呼叫,保證圖片在1000以下
// 重新設定圖片寬高比例,因為小程式一裁剪寬高2000左右的就閃退,這裡限制到1000以下
_resetImageSize(imageInfor) {
let result = imageInfor;
while(result.width > 1000 && result.height > 1000) {
result.width = result.width / 2;
result.height = result.height / 2;
}
return result;
}