系列文章传送门:
微信小程序第一篇:自定义组件详解
微信小程序第二篇:七种主流通信方法详解
微信小程序第三篇:获取页面节点信息
目录
一、封装分享组件
二、定义用户授权方法
三、调用流程
首先我们看一下要完成的效果:
这种场景还是非常常见的,点击分享的时候我们可以转发给好友,或者生成当前页的海报图片保存到手机相册中。分享给好友这个功能可以通过 button 的 open-type 方式实现,那自动保存图片到本地该如何实现呢,让我们来看一看吧:
一、封装分享组件
首先我们要封装一个分享的组件,这样方便在其他的页面中复用。这样就大大减少了代码的冗余,
在 components 文件夹中新建一个组件,下面是完整代码
share.wxml:
<view class="share-sheet-mask flex-column" hidden="{{!showShareSheet}}" catchtap="closeShareSheet"> 微信好友 生成海报 取消
share.js:
Component({ /** * 组件的属性列表 */ properties: { }, /** * 组件的初始数据 */ data: { showShareSheet: false }, /** * 组件的方法列表 */ methods: { openShareSheet() { this.setData({showShareSheet: true}) }, closeShareSheet() { this.setData({showShareSheet: false}); }, genPlayBill() { this.triggerEvent('genPlayBill') }, }})
在点击生成海报的时候,我们向父组件发送了一个事件来调用 genPlayBill 方法,因为这个方法显然不应该在当前组件内定义,应该根据不同场景来定义我们只需要调用它就可以了。
share.wxss:
.flex-column { display: flex; flex-direction: column; align-items: center; justify-content: space-between;}.flex-row { display: flex; flex-direction: row; align-items: center; justify-content: space-between;}.share-sheet-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.60); z-index: 101; justify-content: flex-end;}.share-sheet-mask .share-sheet { padding:0 24rpx; background: #f1f1f1; border-radius: 16rpx 16rpx 0px 0px; width: 100%; box-sizing: border-box;}.share-sheet-mask .share-sheet .items { padding: 48rpx 0 31rpx 0; justify-content: space-around; border-bottom: 0.5px solid rgba(39,36,71,0.20);}.share-sheet-mask .share-sheet .items .item{ text-align: center;}.share-sheet-mask .share-sheet .items .item .ico { width: 80rpx; height: 80rpx; background: #ffffff; border-radius: 50%; box-shadow: 0 0 12rpx 0 rgba(204,204,204,0.60); padding: 0; margin: 0; padding: 0;}/*去除button的默认黑边框*/.share-sheet-mask .share-sheet .items .item .ico::after{ border: none;}.share-sheet-mask .share-sheet .items .item .ico .img { margin: auto;}.share-sheet-mask .share-sheet .items .item .ico .wx-ico { width: 52rpx; height: 40rpx;}.share-sheet-mask .share-sheet .items .item .desc { font-size: 24rpx; font-family: PingFangSC, PingFangSC-Regular; color: #6d6d6d; margin-top: 14rpx;}.share-sheet-mask .share-sheet .items .item .ico .img-ico { width: 44rpx; height: 44rpx;}.share-sheet-mask .share-sheet .cancel-share-sheet { margin: 31rpx auto 80rpx auto; font-size: 32rpx; font-family: PingFangSC, PingFangSC-Regular; color: #272447; text-align: center;}
二、定义用户授权方法
刚刚我们封装了顶部的分享组件,那现在就要去定义保存图片到相册的方法了,我们写代码的时候一定要考虑清楚这段代码是否是可复用的,是否应该剥离出去。显然保存图片到相册这个方法我们应该写在 utils 目录中,因为有很多其他的场景都可以用这个方法,那我们就封装一个公用方法,参数就是图片的地址,成功的回调函数和失败的回调函数。
最复杂的就是用户授权了,我们一起看一下代码结构:
const saveImgToPhotos = (imgPath, succCallback, failedCallback) => { wx.getSetting ({ // 查询所有授权 success(res) { if (res.authSetting['scope.writePhotosAlbum']) { // 用户已经授权 save() // 执行保存函数 }else { // 未授权 wx.authorize({ scope: 'scope.writePhotosAlbum', success() { // 用户同意授权 save() // 执行保存函数 }, fail(err) { // 用户拒绝授权 if (err && err.errMsg.endsWith("auth deny")) { wx.showModal({ title: '授权添加到相册', content: '需要获取您的添加相册权限,请确认授权,否则分享功能无法正常使用', success: function (resolve) { if (resolve.confirm) { // 用户同意设置授权 wx.openSetting({ success(res) { if (res && res.authSetting['scope.writePhotosAlbum']) { save() // 执行保存函数 } }, fail(res) { // 用户拒绝设置授权 console.log(res) failedCallback('没有权限,保存失败') } }) } else { // 用户拒绝设置 failedCallback('没有权限,保存失败') } } }) } else { failedCallback(err && err.errMsg || '保存失败') } } }) } }, }) }
通过wx.authorize()来申请权限的方式是比较繁琐的。因为它的状态比较多,大致可分为:
- 用户未接受或拒绝过此权限,会弹窗询问用户,用户点击同意 —— 可调用相应接口。
- 用户未接受或拒绝过此权限,会弹窗询问用户,用户点击拒绝 —— 打开设置页面。
- 如果用户已授权 —— 可调用相应接口。
- 用户已拒绝授权 —— 打开设置页面。
上述情况的2/4是需要小伙伴们结合 wx.openSetting() 来帮助用户进行二次授权的。
搞定了用户授权这个麻烦事后,下面就是定义我们的 save 保存函数了,这个就很简单了:
let save = function () { wx.saveImageToPhotosAlbum({ filePath: imgPath, success() { succCallback() }, fail(res){ failedCallback(res) } }) }
把这段代码添加到 saveImgToPhotos 方法中就ok了,调用wx.saveImageToPhotosAlbum 方法,参数就是我们传进来的图片地址,成功的话就执行成功的回调,失败就执行失败的回调。
下面是官方的文档说明:
三、调用流程
下面我们就把组件,方法这些东西引入到我们的页面中。在页面的 json 文件中引入组件路径。
把组件引入页面wxml中:
这里的方法就是点击生成海报的时候调用的父组件的方法。
当点击分享的时候展示分享组件:
openShareSheet(e) { this.selectComponent("#share-sheet").openShareSheet() },
在这里通过选择器可以直接调用子组件中的方法,来控制分享组件的显示与隐藏。
genTimelineImage(e) { wx.showLoading({ title: "海报生成中", icon: "loading", mask: true, }) const imgSrc = `路径` wx.getImageInfo({ src: imgSrc, }) .then((res) => { wx.hideLoading() this.imgTempPath = res.path this.saveTimelineImg() }) .catch((err) => console.log(err)) }, saveTimelineImg: function () { saveImgToPhotos(this.imgTempPath, function(){ this.selectComponent("#share-sheet").closeShareSheet() }.bind(this), function(errMsg) { this.selectComponent("#share-sheet").closeShareSheet() }.bind(this)) },
当我们点击生成海报调用 genTimelineImage 方法的时候,通过 wx.getImageInfo 方法读取想要保存图片的临时下载路径,把他保存到外部定义的一个变量中,这样方便我们在 utils 目录中定义的 saveImgToPhotos 方法调用。这样我们整个的流程就over啦!