该文件主要执行分享前的裁剪
微信后台的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;
}