主要步骤
1、把海报样式用标签先写好,方便画图时可以比对2、用canvas进行画图,canvas要注意定好宽高
3、canvas利用wx.canvasToTempFilePath这个api将canvas转化为图片
4、将转化好的图片链接放入image标签里
5、再利用wx.saveImageToPhotosAlbum保存图片
坑点
1、用canvas进行画图的时候要注意画出来的图的大小一定要是你用标签写好那个样式的两倍大小,比如你的海报大小是400600的大小,那你用canvas画的时候大小就要是8001200,宽高可以写在样式里,如果你画出来的图跟你海报图是一样的大小的话生成的图片是会很模糊的,所以才需要放大两倍。2、画图的时候要注意尺寸的转化,如果你是用rpx做单位的话,就要对单位进行转化,因为canvas提供的方法都是经px为单位的,所以这一点要注意一下,px转rpx的公式是w/750z2,w是手机屏幕宽度screenWidth,可以通过wx.getSystemInfo获取,z是你需要画图的单位,2就是乘以两倍大小。
3、图片来源问题,因为canvas不支持网络图片画图,所以你的图片要么是固定的,如果不是固定的,那就要用wx.downloadFile下载后得到一个临时路径才行
4、小程序码问题,小程序需要后台请求接口后返回一个二进制的图片,因为二进制图片canvas也是不支持的,所以也是要用wx.downloadFile下载后得到一个临时路径,或者可以叫后台直接返回一个小程序码的路径给你
5、这里保存的时候是有个授权提醒的,如果拒绝的话再次点击就没有反应了,所以这里我做了一个判断是否有授权的,如果没有就弹窗提醒,确认的话会打开设置页面,确认授权后再次返回就行了,这里有个坑注意下,就是之前拒绝后再进入设置页面确认授权返回页面时保存图片会不成功,官方还没解决,我是加了个setTimeOut处理的,详情可以看这里 https://developers.weixin.qq.com/community/develop/doc/000c46600780f0fa68d7eac345a400
代码实现
<style lang="less">
.share-cover{
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: rgba(0,0,0,.5);
z-index: 101;
}
.share-pic-box{
width: 670rpx;
left: 50%;
height: 300rpx;
margin-left: -335rpx;
top: 120rpx;
position: relative;
}
.share-pic{
width: 670rpx;
height: 744rpx;
border-radius: 12rpx;
background: #fff;
margin-bottom: 40rpx;
overflow: hidden;
}
.share-tips{
width: 566rpx;
height: 88rpx;
line-height: 88rpx;
text-align: center;
font-size: 34rpx;
color: #fff;
background: #2ca2ed;
border-radius: 12rpx;
}
.close-share{
width: 50rpx;
height: 50rpx;
position: absolute;
top: -25rpx;
right: -25rpx;
border-radius: 50%;
z-index: 101;
background-color: #fff;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASBAMAAACk4JNkAAAALVBMVEUAAAAzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMFCKs1AAAADnRSTlMAAwGYnKilo/Tpjn6RhfLwgGgAAAB3SURBVAjXY7hxiAEEhLsZ+p4oABmMcS8Z7N45AVmi714xiL8DCjLGvTNiYKx75wQUeqzAABJUBAkxgARdwUIgwXcgIbAgVAik8QmEJQqUdYIKmYEFQWYp5gEFIcaLAQUhxjOCBP3AZokBXdAHMgso+JJh5yKoSwHamjhPbLDp2gAAAABJRU5ErkJggg==);
background-size: 18rpx 18rpx;
background-repeat: no-repeat;
background-position: center center;
}
.sharePic{
width: 670rpx;
height: 744rpx;
}
.canvas{
width: 1340rpx;
height: 1488rpx;
position: fixed;
top: -1000000rpx;
}
</style>
<template>
<view class="container">
<button @tap="showPic">点击生成海报</button>
<!-- 分享 S -->
<view class="share-cover" wx:if="{{showSharePic}}" catchtouchmove='true'>
<view class="share-pic-box">
<view class="share-pic">
<image src="{{sharePicUrl}}" class="sharePic"></image>
</view>
<button class="share-tips" catchtap='savePic'>保存图片</button>
<view class="close-share" catchtap='closeShare'></view>
</view>
</view>
<!-- 分享 E -->
<!-- canvas S -->
<canvas canvas-id="shareFrends" class="canvas"></canvas>
<!-- canvas E -->
</view>
</template>
<script>
import wepy from 'wepy'
export default class Index extends wepy.page {
config = {
navigationBarTitleText: 'test'
}
components = {
}
data = {
showSharePic: false, // 分享海报显示隐藏
sharePicUrl: '', // 生成海报连接
_selData: {
logoUrl: 'http://h.hiphotos.baidu.com/image/pic/item/29381f30e924b8996ea907f264061d950b7bf667.jpg', //分享图
headIcon: 'https://wx.qlogo.cn/mmhead/RMCO0pDV4UZ5AJGALYibMxL7AQUibc3gJzFqNflYNDmdo/64', //头像
codeLogo: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1548140435403&di=7a7381de7263f358911cde179bc7ab2a&imgtype=0&src=http%3A%2F%2Fimg.zhichiwangluo.com%2Fzcimgdir%2Falbum%2Ffile_5aebd55e797ce.jpg', //小程序码
},
}
computed = {
}
methods = {
showPic() {
let sharePicUrl = this.data.sharePicUrl;
if (sharePicUrl != '') {
this.showSharePic = true
} else {
wx.showToast({
title: '图片生成中',
mask: true,
icon: 'loading',
duration: 100000
})
this.share = false
let logo = '';
let headIcon = '';
let code = '';
this.getHead().then(headUrl => {
headIcon = headUrl
return this.getLogo()
}).then(logoUrl => {
logo = logoUrl;
return this.getCode()
}).then(codeUrl => {
code = codeUrl
this.drawImg(logo, headIcon, code);
})
}
}
}
// 绘图
drawImg (logo, headIcon, code) {
console.log(logo)
console.log(headIcon)
console.log(code)
let title = '腾讯首家线上社区上线啦' // 标题
let authorName = 'var 有缘' // 名称
let w = 0
wx.getSystemInfo({
success: function(res) {
w = res.screenWidth
}
})
let ctx = wx.createCanvasContext('shareFrends')
ctx.fillStyle = '#ffffff'
ctx.fillRect(0, 0, w / 750 * 670 *2, w/ 750 * 744 * 2)
if (title.length > 17) {
title = title.slice(0 ,17) + '...'
}
//绘制logo
ctx.drawImage(logo, 0, 0, w / 750 * 670 * 2, w / 750 * 380 * 2, 0, 0)
//绘制标题
ctx.setFontSize(w / 750 * 34 * 2)
ctx.setFillStyle('#333333')//文字颜色
ctx.fillText(title, w / 750 * 32 * 2, w / 750 * 430 * 2)
//绘制头像、昵称
ctx.save()//保存当前的绘图上下文。
ctx.beginPath()//开始创建一个路径
//画一个圆形裁剪区域
ctx.arc(w / 750 * 52 * 2, w / 750 * 486 * 2, w / 750 * 20 * 2, 0, 2 * Math.PI, false)
ctx.clip()//裁剪
//绘制图片
ctx.drawImage(headIcon, w / 750 * 32 * 2, w / 750 * 466 * 2, w / 750 * 40 * 2, w / 750 * 40 * 2)
ctx.restore()//恢复之前保存的绘图上下文
ctx.setFontSize(w / 750 * 24 * 2)
ctx.setFillStyle('#333333');
//绘制文本
ctx.fillText(authorName, w / 750 * 82 * 2, w / 750 * 495 * 2)
//绘制线条
ctx.moveTo(w / 750 * 32 * 2, w / 750 * 539 * 2);
ctx.lineTo(w / 750 * 638 * 2, w / 750 * 539 * 2);
ctx.setLineWidth = 1;
ctx.setStrokeStyle('#eeeeee')
ctx.stroke();
//绘制左下文案
ctx.setFontSize(w / 750 * 28 * 2)
ctx.setFillStyle('#333333');
//绘制文本
ctx.fillText('性感官方,在线解答', w / 750 * 32 * 2, w / 750 * 593 * 2)
ctx.setFontSize(w / 750 * 22 * 2)
ctx.setFillStyle('#aaaaaa');
//绘制文本
ctx.fillText('答疑,解惑,反馈,应有尽有', w / 750 * 32 * 2, w / 750 * 638 * 2)
ctx.setFontSize(w / 750 * 22 * 2)
ctx.setFillStyle('#aaaaaa');
//绘制文本
ctx.fillText('陪您嗨翻天!', w / 750 * 32 * 2, w / 750 * 672 * 2)
//绘制二维码
ctx.drawImage(code, w / 750 * 518 * 2, w / 750 * 564 * 2, w / 750 * 120 * 2, w / 750 * 120 * 2);
ctx.setFontSize(w / 750 * 20 * 2)
ctx.setFillStyle('#aaaaaa');
//绘制文本
ctx.fillText('长按扫码查看', w / 750 * 518 * 2, w / 750 * 705 * 2)
ctx.draw(false, () => {
//调用接口将画布转换为图片
wx.canvasToTempFilePath({
x: 0,
y: 0,
fileType: 'jpg',
quality: 1,
width: w / 750 * 670 * 2,
height: w / 750 * 744 * 2,
destWidth: w / 750 * 670 * 2,
destHeight: w / 750 * 744 * 2,
canvasId: 'shareFrends',
success: res => {
wx.hideToast();
this.setData({
sharePicUrl: res.tempFilePath //生成的图片路径
}, () => {
//渲染完后再显示分享海报
this.setData({
share: false,
showSharePic: true
})
})
},
fail(err) {
wx.showToast({
title: '图片生成失败,请稍候再试!',
icon: 'none',
mask: true
})
}
})
})
}
//获取头像
getHead() {
return new Promise((resolve, reject) => {
wx.downloadFile({
url: this._selData.headIcon,
success: res => {
resolve(res.tempFilePath)
}
})
})
}
//获取logo
getLogo() {
return new Promise((resolve, reject) => {
wx.downloadFile({
url: this._selData.logoUrl,
success: res => {
resolve(res.tempFilePath);
},
fail: (err) => {
console.log(er)
}
})
})
}
//获取二维码
getCode() {
return new Promise((resolve, reject) => {
let tid = this._selData.tid;
wx.downloadFile({
url: this._selData.codeLogo,
success: res => {
resolve(res.tempFilePath);
},
fail: (err) => {
console.log(er)
}
})
})
}
//关闭分享海报
closeShare() {
this.setData({
showSharePic: false
})
}
//保存图片
savePic() {
let sharePicUrl = this.data.sharePicUrl;
wx.getSetting({
success: res => {
if (res.authSetting['scope.writePhotosAlbum'] == false) {
wx.showModal({
title: '提示',
content: '是否授权将相册保存到相册?',
confirmColor: '#2ca2ed',
success: res => {
//点击确定打开授权设置
if (res.confirm) {
wx.openSetting({
success: res => {
setTimeout(() => {
if (res.authSetting['scope.writePhotosAlbum'] == true) {
wx.saveImageToPhotosAlbum({
filePath: sharePicUrl,
success: res => {
this.closeShare();
wx.showToast({
title: '保存成功!',
icon: 'success',
mask: true
})
},
fail: err => {
wx.showToast({
title: '保存失败!',
icon: 'none',
mask: true
})
}
})
} else {
wx.showToast({
title: '保存失败!',
icon: 'none',
mask: true
})
}
}, 500)
}
})
}
}
})
} else {
wx.saveImageToPhotosAlbum({
filePath: sharePicUrl,
success: res => {
this.closeShare();
wx.showToast({
title: '保存成功!',
icon: 'success',
mask: true
})
}
})
}
}
})
}
onLoad() {
}
}
</script>
复制代码