前言
实现海报?你想到的应该是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
。如图: