前言
实现海报?你想到的应该是html2canvas
吧,但,这里是小程序,好像并不通用。只能用canvas
一笔一划去描述了吗?答案肯定是不对的,今天介绍一个Painter插件,它可以帮助你快速完成小程序上的海报功能。
想到小程序中有如此大量的生成图片需求,而 Canvas 生成方法又是如此难用和坑爹(有关小程序的坑,可看 https://github.com/Kujiale-Mobile/MP-Keng )。我们就想到可不可以做一款可以很方便生成图片,并且还能屏蔽掉直接使用 Canvas 的一些坑的库呢?对此我们发起了 “画家计划
— 通过 json 数据形式,来进行动态渲染并绘制出图片”。
前期准备
去github下载插件需要的文件。下载地址:https://github.com/Kujiale-Mobile/Painter
。下载文件后找到文件里面的components/painter,复制整个painter文件夹,到你小程序项目的component目录下,若考虑该文件较大,可以采用分包的形式,将文件放入分包中。
组件形式使用插件
需要绘制海报的页面的.json中添加组件,或者在app.json中添加全局的组件。
-
{
"usingComponents"
:
-
{
-
"painter"
:
"./Components/painter/painter"
-
}
-
}
绘制界面样式、数据
既然要绘制海报,我们必然需要准备好海报的内容。如:用到的文案、真实的数据、海报素材,包括视频文件、图片文件等等。
准备好以上东西我们需要将这些东西绘制在海报上,我们需要按照一定的格式才能更方便的绘制,而不是像canvas那样一点点去绘制。
这里推荐使用工具Painter海报生成Json工具[https://lingxiaoyi.github.io/painter-custom-poster
] 网站。因为使用painter插件可以让我们只要传输Json格式的数据给它,它就能帮我们绘制好页面。在网站内调整好布局后点击复制代码即可拷贝出如下Json格式的代码。
-
export
default class LastMayday {
-
palette(params) {
-
return ({
-
width:
"750rpx",
-
height:
"1200rpx",
-
background:
"#FEF8F3",
-
views: [{
-
type:
"image",
-
url:
`***/weapp/poster/poster_${params.posterNum}.jpg`,
-
css: {
-
width:
"750rpx",
-
height:
"1200rpx",
-
top:
"0px",
-
left:
"0px",
-
mode:
"scaleToFill"
-
}
-
},
-
{
-
type:
"image",
-
url:
`${params.avatar}`,
-
css: {
-
width:
"100rpx",
-
height:
"100rpx",
-
top:
"124rpx",
-
left:
"64rpx",
-
borderRadius:
"100rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000",
-
borderWidth:
"1rpx",
-
borderColor:
"#fff"
-
}
-
},
-
{
-
type:
"text",
-
text:
`${params.userName}`,
-
css: {
-
color:
"#fff",
-
width:
"200rpx",
-
top:
"135rpx",
-
left:
"186rpx",
-
fontSize:
"32rpx",
-
fontWeight:
"bold",
-
textAlign:
"left",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
`${params.className}`,
-
css: {
-
color:
"#fff",
-
width:
"300rpx",
-
top:
"175rpx",
-
left:
"186rpx",
-
fontSize:
"30rpx",
-
textAlign:
"left",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
`大学习第${params.term}期`,
-
css: {
-
color:
"#fff",
-
width:
"300rpx",
-
top:
"135rpx",
-
left:
"398rpx",
-
fontSize:
"30rpx",
-
fontWeight:
"bold",
-
textAlign:
"right",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=1?'***/weapp/badge/badge_1.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"86rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=2?'***/weapp/badge/badge_2.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"182rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=3?'***/weapp/badge/badge_3.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"278rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=4?***/weapp/badge/badge_4.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"374rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=5?'***/weapp/badge/badge_5.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"470rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=6?'*****/weapp/badge/badge_6.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"566rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"text",
-
text:
"完成率达到",
-
css: {
-
color:
"#fff",
-
width:
"300rpx",
-
top:
"680rpx",
-
left:
"105rpx",
-
fontSize:
"40rpx",
-
textAlign:
"left",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
`${params.ratio}%`,
-
css: {
-
color:
"#ff4000",
-
width:
"200rpx",
-
top:
"678rpx",
-
left:
"307rpx",
-
fontSize:
"44rpx",
-
fontWeight:
"bold",
-
textAlign:
"left",
-
shadow:
"1rpx 1rpx 2rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
"速度超过了全国",
-
css: {
-
color:
"#fff",
-
width:
"300rpx",
-
top:
"746rpx",
-
left:
"105rpx",
-
fontSize:
"40rpx",
-
textAlign:
"left",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
`${params.classNum}`,
-
css: {
-
color:
"#ff4000",
-
width:
"150rpx",
-
top:
"814rpx",
-
left:
"105rpx",
-
fontSize:
"46rpx",
-
fontWeight:
"bold",
-
textAlign:
"left",
-
shadow:
"1rpx 1rpx 2rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
`个班级`,
-
css: {
-
color:
"#fff",
-
width:
"400rpx",
-
top:
"818rpx",
-
left:
`${105+(params.classNum.toString().length)*30}rpx`,
-
fontSize:
"40rpx",
-
textAlign:
"left",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
]
-
});
-
}
-
}
在painter同级目录下新建一个paletle文件夹,然后在其下新建一个poster.js文件。如下:
这个文件就是用来处理数据和绘制海报的Js。
使用poster文件
在需要绘制海报的页面的.js中引用文件。
import Poster from '../../Components/palette/poster'
然后在你需要开始绘制海报的地方执行如下代码:
-
let posterParams = {
-
avatar:
this.
data.avatar,
-
userName:
this.
data.userName,
-
className:
this.
data.className,
-
term:
this.
data.term,
-
ratio:
this.
data.ratio,
-
classNum:
this.
data.classNum >=
100000 ?
'10万+' :
this.
data.classNum,
-
medalNum:
this.
data.medalNum,
-
posterNum:
this.
data.currentIndex
-
}
-
wx.showToast({
-
title:
'海报绘制中',
-
icon:
'loading',
-
duration:
3000,
-
})
-
this.setData({
-
paintPallette: new Poster().palette(posterParams),
-
});
可以看到,我们是通过new
创建一个Poster实例,然后调用实例的方法palette
,方法可以传一个对象,这个对象就是海报需要动态修改的数据。
使用组件
在需要绘制海报的页面的.wxml中使用组件。
<painter customStyle='position: absolute; left: -9999rpx;' palette="{{paintPallette}}" bind:imgOK="onImgOK" bind:imgErr="onImgErr"/>
其中customStyle:是插件支持的自定义样式,如果需要在海报绘制成功后不希望出现在页面上,可以采用如上的position: absolute; left: -9999rpx;
palette:是绘制海报内容的数据,可以传输从服务器返回过来的数据。
imgOK:是海报绘制成功后的回调,imgErr:是海报绘制失败的回调。
-
onImgOK(
e) {
-
that.
setData({
-
imagePath: e.
detail.
path,
//绘制后的图片临时地址
-
})
-
}
踩坑预警
1、使用Painter海报生成Json工具复制的代码会有一部分是没有用的,且加上会出错。
可以参考我上面的样式属性。需要用到其他样式属性的可以一点点加上查看效果。
2、绘制出来的海报很模糊。我们需要在绘制图片时加上设备的分辨率,代码在拷贝下来的painter.js,里面找到wx.canvasToTempFilePath...
这句代码,绘制的宽高加上getApp().systemInfo.pixelRatio
。如图:
</article>
微信小程序绘制海报
<div id="blogColumnPayAdvert">
<div class="column-group">
<div class="column-group-item column-group0 column-group-item-one">
<div class="item-l">
<a class="item-target" href="https://blog.youkuaiyun.com/qq_26975307/category_9513335.html" target="_blank" title="微信小程序" data-report-click="{"spm":"1001.2101.3001.6332"}">
<img class="item-target" src="https://img-blog.csdnimg.cn/20201014180756780.png?x-oss-process=image/resize,m_fixed,h_64,w_64" alt="">
<span class="title item-target">
<span>
<span class="tit">微信小程序</span>
<span class="dec">专栏收录该内容</span>
</span>
</span>
</a>
</div>
<div class="item-m">
<span>8 篇文章</span>
<span>0 订阅</span>
</div>
<div class="item-r">
<a class="item-target article-column-bt articleColumnFreeBt" data-id="9513335">订阅专栏</a>
</div>
</div>
</div>
</div>
<article class="baidu_pl">
<div id="article_content" class="article_content clearfix">
<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-b3c43d3711.css">
<div id="content_views" class="htmledit_views">
<h2><a name="t0"></a>前言</h2>
实现海报?你想到的应该是html2canvas
吧,但,这里是小程序,好像并不通用。只能用canvas
一笔一划去描述了吗?答案肯定是不对的,今天介绍一个Painter插件,它可以帮助你快速完成小程序上的海报功能。
想到小程序中有如此大量的生成图片需求,而 Canvas 生成方法又是如此难用和坑爹(有关小程序的坑,可看 https://github.com/Kujiale-Mobile/MP-Keng )。我们就想到可不可以做一款可以很方便生成图片,并且还能屏蔽掉直接使用 Canvas 的一些坑的库呢?对此我们发起了 “画家计划
— 通过 json 数据形式,来进行动态渲染并绘制出图片”。
前期准备
去github下载插件需要的文件。下载地址:https://github.com/Kujiale-Mobile/Painter
。下载文件后找到文件里面的components/painter,复制整个painter文件夹,到你小程序项目的component目录下,若考虑该文件较大,可以采用分包的形式,将文件放入分包中。
组件形式使用插件
需要绘制海报的页面的.json中添加组件,或者在app.json中添加全局的组件。
-
{
"usingComponents"
:
-
{
-
"painter"
:
"./Components/painter/painter"
-
}
-
}
绘制界面样式、数据
既然要绘制海报,我们必然需要准备好海报的内容。如:用到的文案、真实的数据、海报素材,包括视频文件、图片文件等等。
准备好以上东西我们需要将这些东西绘制在海报上,我们需要按照一定的格式才能更方便的绘制,而不是像canvas那样一点点去绘制。
这里推荐使用工具Painter海报生成Json工具[https://lingxiaoyi.github.io/painter-custom-poster
] 网站。因为使用painter插件可以让我们只要传输Json格式的数据给它,它就能帮我们绘制好页面。在网站内调整好布局后点击复制代码即可拷贝出如下Json格式的代码。
-
export
default class LastMayday {
-
palette(params) {
-
return ({
-
width:
"750rpx",
-
height:
"1200rpx",
-
background:
"#FEF8F3",
-
views: [{
-
type:
"image",
-
url:
`***/weapp/poster/poster_${params.posterNum}.jpg`,
-
css: {
-
width:
"750rpx",
-
height:
"1200rpx",
-
top:
"0px",
-
left:
"0px",
-
mode:
"scaleToFill"
-
}
-
},
-
{
-
type:
"image",
-
url:
`${params.avatar}`,
-
css: {
-
width:
"100rpx",
-
height:
"100rpx",
-
top:
"124rpx",
-
left:
"64rpx",
-
borderRadius:
"100rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000",
-
borderWidth:
"1rpx",
-
borderColor:
"#fff"
-
}
-
},
-
{
-
type:
"text",
-
text:
`${params.userName}`,
-
css: {
-
color:
"#fff",
-
width:
"200rpx",
-
top:
"135rpx",
-
left:
"186rpx",
-
fontSize:
"32rpx",
-
fontWeight:
"bold",
-
textAlign:
"left",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
`${params.className}`,
-
css: {
-
color:
"#fff",
-
width:
"300rpx",
-
top:
"175rpx",
-
left:
"186rpx",
-
fontSize:
"30rpx",
-
textAlign:
"left",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
`大学习第${params.term}期`,
-
css: {
-
color:
"#fff",
-
width:
"300rpx",
-
top:
"135rpx",
-
left:
"398rpx",
-
fontSize:
"30rpx",
-
fontWeight:
"bold",
-
textAlign:
"right",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=1?'***/weapp/badge/badge_1.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"86rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=2?'***/weapp/badge/badge_2.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"182rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=3?'***/weapp/badge/badge_3.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"278rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=4?***/weapp/badge/badge_4.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"374rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=5?'***/weapp/badge/badge_5.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"470rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"image",
-
url:
`${params.medalNum>=6?'*****/weapp/badge/badge_6.png':''}`,
-
css: {
-
width:
"96rpx",
-
top:
"280rpx",
-
left:
"566rpx",
-
mode:
"scaleToFill",
-
shadow:
"2rpx 2rpx 4rpx #000"
-
},
-
},
-
{
-
type:
"text",
-
text:
"完成率达到",
-
css: {
-
color:
"#fff",
-
width:
"300rpx",
-
top:
"680rpx",
-
left:
"105rpx",
-
fontSize:
"40rpx",
-
textAlign:
"left",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
`${params.ratio}%`,
-
css: {
-
color:
"#ff4000",
-
width:
"200rpx",
-
top:
"678rpx",
-
left:
"307rpx",
-
fontSize:
"44rpx",
-
fontWeight:
"bold",
-
textAlign:
"left",
-
shadow:
"1rpx 1rpx 2rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
"速度超过了全国",
-
css: {
-
color:
"#fff",
-
width:
"300rpx",
-
top:
"746rpx",
-
left:
"105rpx",
-
fontSize:
"40rpx",
-
textAlign:
"left",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
`${params.classNum}`,
-
css: {
-
color:
"#ff4000",
-
width:
"150rpx",
-
top:
"814rpx",
-
left:
"105rpx",
-
fontSize:
"46rpx",
-
fontWeight:
"bold",
-
textAlign:
"left",
-
shadow:
"1rpx 1rpx 2rpx #000"
-
}
-
},
-
{
-
type:
"text",
-
text:
`个班级`,
-
css: {
-
color:
"#fff",
-
width:
"400rpx",
-
top:
"818rpx",
-
left:
`${105+(params.classNum.toString().length)*30}rpx`,
-
fontSize:
"40rpx",
-
textAlign:
"left",
-
shadow:
"4rpx 4rpx 6rpx #000"
-
}
-
},
-
]
-
});
-
}
-
}
在painter同级目录下新建一个paletle文件夹,然后在其下新建一个poster.js文件。如下:
这个文件就是用来处理数据和绘制海报的Js。
使用poster文件
在需要绘制海报的页面的.js中引用文件。
import Poster from '../../Components/palette/poster'
然后在你需要开始绘制海报的地方执行如下代码:
-
let posterParams = {
-
avatar:
this.
data.avatar,
-
userName:
this.
data.userName,
-
className:
this.
data.className,
-
term:
this.
data.term,
-
ratio:
this.
data.ratio,
-
classNum:
this.
data.classNum >=
100000 ?
'10万+' :
this.
data.classNum,
-
medalNum:
this.
data.medalNum,
-
posterNum:
this.
data.currentIndex
-
}
-
wx.showToast({
-
title:
'海报绘制中',
-
icon:
'loading',
-
duration:
3000,
-
})
-
this.setData({
-
paintPallette: new Poster().palette(posterParams),
-
});
可以看到,我们是通过new
创建一个Poster实例,然后调用实例的方法palette
,方法可以传一个对象,这个对象就是海报需要动态修改的数据。
使用组件
在需要绘制海报的页面的.wxml中使用组件。
<painter customStyle='position: absolute; left: -9999rpx;' palette="{{paintPallette}}" bind:imgOK="onImgOK" bind:imgErr="onImgErr"/>
其中customStyle:是插件支持的自定义样式,如果需要在海报绘制成功后不希望出现在页面上,可以采用如上的position: absolute; left: -9999rpx;
palette:是绘制海报内容的数据,可以传输从服务器返回过来的数据。
imgOK:是海报绘制成功后的回调,imgErr:是海报绘制失败的回调。
-
onImgOK(
e) {
-
that.
setData({
-
imagePath: e.
detail.
path,
//绘制后的图片临时地址
-
})
-
}
踩坑预警
1、使用Painter海报生成Json工具复制的代码会有一部分是没有用的,且加上会出错。
可以参考我上面的样式属性。需要用到其他样式属性的可以一点点加上查看效果。
2、绘制出来的海报很模糊。我们需要在绘制图片时加上设备的分辨率,代码在拷贝下来的painter.js,里面找到wx.canvasToTempFilePath...
这句代码,绘制的宽高加上getApp().systemInfo.pixelRatio
。如图:
</article>