微信小程序canvas导出海报到相册

在以往的项目中经常有导出页面海报的需求,不同的是这次是在小程序中,在h5中我们常用html2canvas这个插件,但是在小程序中显然无法使用。那只有用微信的canvas一点一点画了,这工作量想想就有点怕,还好有轮子哥封装了个小程序绘图插件 Painter

wx.createSelectorQuery()节点信息

小程序也给我提供了节点查询的api,我的做法是把样式写在节点的data属性里,只需要遍历这些节点就能快速的生成绘制的对象参数,就不用一个个自己去写了

wxml代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  <view id="main">
<view class="top-head">
<image src="../../img/logo.png" data-type="image" data-img="/img/logo.png" class="draw"/>
</view>
<view class="balck-line draw" data-type="rect" data-color="#000" ></view>
<image src="../../img/title.png" class="top-bg draw" data-type="image" data-img="/img/title.png"/>
<view class="balck-line draw" data-type="rect" data-color="#000"></view>
<view class="citylevel-wrap">
<image src="{{rank_img}}" alt="" class="rankimg draw" data-type="image" data-img="{{rank_img}}"/>
<view class="chart-tip">
<image src="../../img/i.png" data-type="image" data-img="/img/i.png" class="draw"></image>
<text class="draw right" data-type="text" data-text="{{nowYear}}城市商业魅力排行榜中仅纳入337个地级及以上城市数据计算。" data-color="#969696" data-font="22" data-bold="0" data-wrap="1">{{nowYear}}城市商业魅力排行榜中仅纳入337个地级及以上城市数据计算。</text>
</view>
</view>
<view class="chart-line draw" data-type="rect" data-color="#C8C8C8"></view>
</view>
<view class="btn-wrap">
<button open-type='share' class="left">
<image src="../../img/weixin.png" />
</button>
<button open-type="openSetting" class="auth" wx:if="{{!photoAuth}}" bindopensetting="drawPic">
<image src="../../img/pic.png"/>
</button>
<image src="../../img/pic.png" class="right" wx:if="{{photoAuth}}" bindtap="drawPic"/>
</view>
<view class="footer">
<view bindtap="jumWeb" data-url="http://www.baidu.com">购买{{nowYear}}报告册</view>
<view class="line"></view>
<view bindtap="jumWeb" data-url="http://yc.ihangwei.com">跳转知城数据平台</view>
</view>
<painter style="position: absolute; top: -99999rpx;" palette="{{imgDraw}}" bind:imgOK="onImgOK" widthPixels="2500"/>

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
var utils = require("../../utils/util.js")
Page({
data:{
imgDraw: {}, //绘制图片的大对象
sharePath: '', //生成的分享图
nowYear:new Date().getFullYear(),
rank_img:"",
photoAuth:true,
},
onLoad:function(options){
this.getCountryDetail()
},
// 保存图片
save() {
var path = this.data.sharePath;
var that = this;
wx.getSetting({
success: res => {
let authSetting = res.authSetting
if (authSetting['scope.writePhotosAlbum']) {//有权限
wx.showLoading({title: '正在保存...',mask: true})
}
wx.saveImageToPhotosAlbum({
filePath:path,
success: function (data) {
wx.hideLoading()
utils.Toast('保存到系统相册成功')
that.setData({photoAuth:true})
},
fail: function (err) {
if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
utils.Toast('保存失败,请先授权')
that.setData({photoAuth:false})
}
},
})
}
})
},
drawPic() {
var that =this;
wx.showLoading({title: '生成海报中...',mask: true})
var query = wx.createSelectorQuery();
var queryMain = wx.createSelectorQuery();
var width,height,paddingTop;
queryMain.select('#main').boundingClientRect(function (nodes){
console.log(nodes)
width = nodes.width;
height = nodes.height;
paddingTop = nodes.top;
}).exec();
query.selectAll('.draw').boundingClientRect(function (nodes) {
var arr = []
nodes.forEach(item=>{
if(item.dataset.type=='text'){
arr.push({
type: 'text',
text: item.dataset.text,
css: {
top: (item.top-paddingTop)+'px',
fontSize: item.dataset.font+'rpx',
left: item.left+'px',
color: item.dataset.color,
fontWeight:item.dataset.bold=='1'?"bold":"normal",
fontFamily:item.dataset.family
}
})
}
if(item.dataset.type=='rect'){
arr.push({
type: 'rect',
css: {
top: (item.top-paddingTop)+'px',
width:item.width+'px',
height:item.height+'px',
left: item.left+'px',
color: item.dataset.color,
borderRadius:item.dataset.circle=='1'?item.height/2+'px':'',
}
})
}
if(item.dataset.type=='image'){
arr.push({
type: 'image',
url: item.dataset.img,
css: {
top: (item.top-paddingTop)+'px',
left: item.left+'px',
width:item.width+'px',
height:item.height+'px'
}
})
}
})
that.setData({
imgDraw: {
width: width+'px',
height: height+120+'px',
views: that.drawBottom(arr,height)
}
})
}).exec();
},
drawBottom(arr,height){
arr.push(
{
type: 'image',
url: '/img/erwm_img@2x.png',
css: {
top: height+22.5+'px',
left:'30rpx',
width:'150rpx',
height:'150rpx',
borderRadius:'75rpx'
}
},
{
type: 'image',
url: '/img/scan.png',
css: {
top: height+42+'px',
left:'197rpx',
width:'225rpx',
height:'76rpx'
}
},
{
type: 'image',
url: '/img/citys.png',
css: {
top: height+32+'px',
left:'554rpx',
width:'166rpx',
height:'113rpx'
}
}
)
return arr
},
onImgOK(e) {
wx.hideLoading()
this.setData({
sharePath: e.detail.path,
})
this.save()
},
getCountryDetail(){
wx.showLoading({title: '加载中...',mask: true})
var data = {
year:'',
}
utils.ajax("/Applets/CityRank/countryDetail",data).then(res=>{
wx.hideLoading()
if(res.data.code =='20000'){
this.setData({rank_img:res.data.data.rank_img})
}else{
utils.Toast(res.data.msg)
}
})
},
getProvince(){
utils.ajax("/Applets/CityRank/provinceList",{year:'2019'}).then(res=>{
if(res.data.code =='20000'){

this.setData({provinceData:res.data.data})
}else{
utils.Toast(res.data.msg)
}
})
},
jumWeb(e){
var url = e.currentTarget.dataset.url;
wx.navigateTo({url:'../webview/webview?url='+url})
},
//分享
onShareAppMessage: function (ops) {
return {
title: '新一线城市研究所',
path: `pages/allCity/allCity`,
}
}
})
0%