系列文章传送门:
目录
首先我们看一下要完成的效果:

这种场景还是非常常见的,点击分享的时候我们可以转发给好友,或者生成当前页的海报图片保存到手机相册中。分享给好友这个功能可以通过 button 的 open-type 方式实现,那自动保存图片到本地该如何实现呢,让我们来看一看吧:
首先我们要封装一个分享的组件,这样方便在其他的页面中复用。这样就大大减少了代码的冗余,
在 components 文件夹中新建一个组件,下面是完整代码
share.wxml:
<!-- 底部自定义分享菜单栏 -->
<view class="share-sheet-mask flex-column" hidden="{{!showShareSheet}}" catchtap="closeShareSheet">
<view class="share-sheet">
<view class="items flex-row">
<view class="item flex-column">
<button class="ico flex-row" open-type="share">
<image class="img wx-ico" src="../../images/ico_wx.svg"></image>
</button>
<view class="desc">微信好友</view>
</view>
<view class="item flex-column">
<button class="ico flex-row" catchtap="genPlayBill">
<image class="img img-ico" src="../../images/ico_img.svg"></image>
</button>
<view class="desc">生成海报</view>
</view>
</view>
<view class="cancel-share-sheet">取消</view>
</view>
</view>
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中:
<share-sheet id="share-sheet" catch:genPlayBill="genTimelineImage" />
这里的方法就是点击生成海报的时候调用的父组件的方法。
当点击分享的时候展示分享组件:
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啦!
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数
我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些
有这些railscast。http://railscasts.com/episodes/218-making-generators-in-rails-3有了这个,你就会知道如何创建样式表和脚手架生成器。http://railscasts.com/episodes/216-generators-in-rails-3通过这个,您可以了解如何添加一些文件来修改脚手架View。我想把两者结合起来。我想创建一个生成器,它也可以创建脚手架View。有点像RyanBates漂亮的生成器或web_app_themegem(https://github.com/pilu/web-app-theme)。我
导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri
前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU