收藏
评论

Painter 一款轻量级的小程序海报生成组件

生成海报相信大家有的人都做过,但是canvas绘图的坑太多。大家可以试试这个组件。然后附上楼下大哥做的可视化拖拽生成painter代码的工具:链接地址https://developers.weixin.qq.com/community/develop/article/doc/000e222d9bcc305c5739c718d56813

Painter

由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 Canvas 功能生成一张带有二维码的图片,然后引导用户下载图片到本地后再分享到朋友圈。而小程序 Canvas 功能是很难用的,往往为了绘制一张简单图片,就得写上一堆 boilerplate code ,而且一不小心还会踩到 Canvas 的各种彩蛋(坑)。我想此时你的心情肯定是这样的。

这边说上几个小程序 Canvas 的坑

  1. Canvas 绘图是用的 px,而在小程序中我们一般使用 rpx 进行相对布局。
  2. 小程序 Canvas 中的 drawImage 方法,在 IDE 中可以直接设置网络图片进行绘制,但在真机上设置网络图片无用。
  3. canvasContext.clip 方法在 iOS 设备上的微信 6.6.6 版本及以下有 bug,会导致该 clip 下面使用的的 restore 方法失效。

画家计划

想到小程序中有如此大量的生成图片需求,而 Canvas 生成方法又是如此难用和坑爹。那我们就想到可不可以做一款可以很方便生成图片,并且还能屏蔽掉直接使用 Canvas 的一些坑的库呢?所以我们发起了 “画家计划— 通过 json 数据形式,来进行动态渲染并绘制出图片”。 Painter 库的整体架构如下:

整体架构

首先,我们定义了一套绘图 JSON 规范,开发者可以根据需求构建生成图片的 Palette(调色板),然后在程序运行过程中把调色板传入给 Painter(画家)。Painter 会调用 Pen(画笔),根据 Palette 内容绘制出对应的图片后返回。

How To Use

运行例子

git clone https://github.com/Kujiale-Mobile/Painter.git

代码下载后,用小程序 IDE 打开后即可使用。

注:请选择小程序项目,非小游戏,例子中无 appid,所以无法在手机上运行,如果需要真机调试,请在打开例子时,填上自己的小程序 id

使用 Painter

  1. 引入代码

    Painter 的核心代码在另一个 repo 中,https://github.com/Kujiale-Mobile/PainterCore.git 。你可以通过以下三种方式进行库的引入:

    一,直接下载代码,拷贝代码到你需要的库中。(不推荐)

    二,submodule 的方式。可以在主项目下执行以下命令。如后续需更新代码,则到对应目录下 pull 最新的代码即可。(推荐)

    git submodule add https://github.com/Kujiale-Mobile/PainterCore.git components/painter
    

    三,subtree 的方式。也一样是在主项目中执行命令。代码更新要复杂点,submodule 和 subtree 的区别请自行 Google。

    git subtree add --prefix=components/painter https://github.com/Kujiale-Mobile/PainterCore.git master
    
  2. 作为自定义组件引入,注意目录为第一步引入的代码所在目录

    "usingComponents":{
      "painter":"/components/painter/painter"
    }
    
  3. 组件接收 palette 字段作为画图数据的数据源, 图案数据以json形式存在,推荐使用“皮肤模板”的方法进行传递,示例代码如下:

    <painter palette="{{data}}" bind:imgOK="onImgOK" />
    
  4. 数据传入后,则会自动进行绘图。绘图完成后,你可以通过绑定 imgOK 或 onImgErr 事件来获得成功后的图片 或失败的原因。

    bind:imgOK="onImgOK"
    bind:imgErr="onImgErr"
    

Palette 规范

如你使用 wxss + wxml 规范进行绘制一样,Painter 需要根据一定的规范来进行图片绘制。当然 Painter 的绘制规范要比 wxml 简单很多。

调色板属性

一个调色板首先需要给予一些整体属性

background: 可以是颜色值,也可以为网络图片的链接,默认为白色
width: 宽度
height: 高度
borderRadius: 边框的圆角(该属性也同样适用于子 view)
views: 里面承载子 view

子 View 属性

当我们把整体的调色板属性构建起来后,里面就可以添加子 View 来进行绘制了。

type content description 自有css
image url 表示图片资源的地址,本地或网络
text text 文本的内容 fontSize: 文字大小,color: 字体颜色(默认为黑色)
rect 矩形 color: 颜色
qrcode content 画二维码 background: 背景颜色(默认为透明色),

布局属性

以上 View ,除去自己拥有的特别属性外,还有以下的通用布局属性

属性 意义
rotate 旋转,按照顺时针旋转的度数,默认不旋转
borderRadius 边界圆角程度,如果是正方形布局,该属性为一半宽或高时,则为圆形
top、right、bottom、left 如 css 中为 absolute 布局时的作用,默认 top 和 left 为 0
align center:中间对齐方式;right:右对齐方式;left:左对齐方式(默认,可不写)

尺寸即其他

1,目前 Painter 中支持两种尺寸单位,px 和 rpx,代表的意思和小程序中一致,此处就不多说。

2,目前子 view 的 css 属性支持 object 或 array。所以意味着,你可以把几个子 view 共用的 css 属性提取出来。做到让 Palette 更加简洁。

3,因为我们的 palette 是以 js 承载的 json,所以意味着你可以在每一个属性中很方便的加上自己的逻辑。也可以把某些属性单独提取出来,让多个 palette 共用,做到模块化。

举个栗子

{
  background: '#eee',
  width: '654rpx',
  height: '400rpx',
  borderRadius: '20rpx',
  views: [
  {
    type: 'image',
    url: 'https://qhyxpicoss.kujiale.com/r/2017/12/04/L3D123I45VHNYULVSAEYCV3P3X6888_3200x2400.jpg@!70q',
    css: {
      top: '48rpx',
      right: '48rpx',
      width: '192rpx',
      height: '192rpx',
    },
  }
  ...
  ],
}

绘制效果如下

License

Copyright (c) 2018 Kujiale

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
最后一次编辑于  2019-09-27
收藏

112 个评论

  • 你好耀眼。
    你好耀眼。
    2019-09-17

    设置textDecoration:line-through,发现删除线偏移一段距离怎么解决

    2019-09-17
    赞同
    回复 5
    • TNT
      TNT
      2019-09-18
      已在另外的帖子回复~
      2019-09-18
      回复
    • 谢志杰
      谢志杰
      2022-06-06回复TNT
      请问getUnlimited返回的图片的二进制buffer数据怎么转换成图片的啊
      2022-06-06
      回复
    • 谢志杰
      谢志杰
      2022-06-06回复TNT
      谢谢
      2022-06-06
      回复
    • 谢志杰
      谢志杰
      2022-06-06回复TNT
      但是如果后端不做 前端能怎么处理啊。。好蒙
      2022-06-06
      回复
    • 谢志杰
      谢志杰
      2022-06-06回复TNT
      听我说 谢谢你
      2022-06-06
      回复
  • 渭城曲
    渭城曲
    2019-09-16

    请问我页面上的数据在哪个index里面怎么拿得到啊“”?

    2019-09-16
    赞同
    回复 3
    • TNT
      TNT
      2019-09-16
      ??什么页面数据
      2019-09-16
      回复
    • 渭城曲
      渭城曲
      2019-09-16回复TNT
      就是生成海报上的文字 怎么传过去?
      2019-09-16
      回复
    • TNT
      TNT
      2019-09-16回复渭城曲
      这边有写一篇文章:https://developers.weixin.qq.com/community/develop/article/doc/000ac686c5c5506f18b87ee825b013
      2019-09-16
      回复
  • fend
    fend
    2019-09-07

    可以文字超过两行 显示省略号吗

    2019-09-07
    赞同
    回复 2
    • TNT
      TNT
      2019-09-09
      可以的哈。
      2019-09-09
      回复
    • TNT
      TNT
      2019-09-09
      设置maxLines为2,设置width: 400rpx,超出这个宽度 2行的就会显示省略号
      2019-09-09
      回复
  • 玉米的小跟班
    玉米的小跟班
    2019-08-26

    可以传参数吗,别人扫码进入小程序,可以获取到这个参数

    2019-08-26
    赞同
    回复 4
    • TNT
      TNT
      2019-08-26
      可以。。参数在你小程序码里 跟生成分享图无关。
      2019-08-26
      回复
    • 玉米的小跟班
      玉米的小跟班
      2019-08-26回复TNT
      感谢大佬回复,请问,你的demo里面,有可以加这个参数api吗,我比较菜,谢谢QAQ
      2019-08-26
      回复
    • 玉米的小跟班
      玉米的小跟班
      2019-08-26回复玉米的小跟班
      我明白了,是在微信公众平台生成的,但那样就固定了参数,有办法生成自己的参数吗,不固定的
      2019-08-26
      回复
    • TNT
      TNT
      2019-08-26回复玉米的小跟班
      这是以前写的:https://www.jianshu.com/p/f925cf125cf8 建议你看看吧。。
      2019-08-26
      回复
  • Sun
    Sun
    2019-08-17

    这个插件可以设置字体间距吗?

    2019-08-17
    赞同
    回复 1
    • TNT
      TNT
      2019-08-19
      暂时不支持哦
      2019-08-19
      回复
  • 侯衍超
    侯衍超
    2019-08-17

    下面这个json,请在手机上运行调试,总是出现绘制异常,频率很高。 @仙

    {"width":"750rpx","height":"3002rpx","background":"#BC443C","views":[{"type":"rect","css":{"width":"710rpx","height":"2634rpx","left":"20rpx","top":"346rpx","color":"#fff"}},{"type":"text","text":"【过验】二號店","css":{"top":"190rpx","left":"375rpx","align":"center","fontSize":"30rpx","color":"#fff"}},{"type":"text","text":"发起了一个抽奖活动","css":{"top":"250rpx","left":"375rpx","align":"center","fontSize":"42rpx","color":"#fff","fontWeight":"bold"}},{"type":"image","url":"https://image.bushishier.com/20190814/15657710589477.jpg","css":{"width":"120rpx","height":"120rpx","left":"315rpx","top":"50rpx","mode":"scaleToFill","borderRadius":"60rpx"}},{"type":"text","text":"一等奖: Adidas Yeezy 350 V2 满天星 × 1","css":{"left":"42rpx","top":"726rpx","width":"660rpx","maxLines":2,"lineHeight":"58rpx","fontSize":"38rpx","color":"#444"}},{"type":"text","text":"二等奖: 【过验】微店鞋类100元优惠券 × 999","css":{"left":"42rpx","top":"1210rpx","width":"660rpx","maxLines":2,"lineHeight":"58rpx","fontSize":"38rpx","color":"#444"}},{"type":"text","text":"三等奖: 【过验】微店鞋类100元优惠券 × 300","css":{"left":"42rpx","top":"1694rpx","width":"660rpx","maxLines":2,"lineHeight":"58rpx","fontSize":"38rpx","color":"#444"}},{"type":"text","text":"08月17日 20:00 自动开奖","css":{"left":"45rpx","top":"1824rpx","width":"644rpx","maxLines":1,"fontSize":"30rpx","color":"#6a737d"}},{"type":"text","text":"长按识别小程序码,参与抽奖","css":{"left":"375rpx","top":"2244rpx","fontSize":"28rpx","color":"#6a737d","align":"center"}},{"type":"text","text":"抽奖说明:【过验】工作室:\nAdidas  Yeezy  Nike Air Jordan系列\n独家过验版本(可过鉴定平台)\n「精工细作 终成大器」\n外观1:1公司货「单独鉴定外观 百分百过鉴定」\n按照公司货标准 拆解开模具做货\n从底面 鞋面 针织鞋带 马克线 中底\n【过验】工作室:\n区别目前國內99%发图卖图无库存靠上家发货的小代理微商\n非大众口中常说的\"莆田货\"\n独家过验版本 85%过鉴定平台","css":{"width":"660rpx","top":"2370rpx","left":"52rpx","fontSize":"28rpx","maxLines":14,"lineHeight":"46rpx","color":"#6a737d"}},{"type":"image","url":"https://image.bushishier.com/20190814/15657743246776.jpg","css":{"width":"660rpx","height":"330rpx","left":"45rpx","top":"372rpx"}},{"type":"image","url":"https://image.bushishier.com/choujiang/banner_default.png","css":{"width":"660rpx","height":"330rpx","left":"45rpx","top":"856rpx"}},{"type":"image","url":"https://image.bushishier.com/choujiang/banner_default.png","css":{"width":"660rpx","height":"330rpx","left":"45rpx","top":"1340rpx"}},{"type":"image","url":"https://image.bushishier.com/20190814/15657746929504.jpg","css":{"width":"250rpx","height":"250rpx","left":"250rpx","top":"1964rpx"}}]}

    2019-08-17
    赞同
    回复 3
    • TNT
      TNT
      2019-08-19
      建议使用 750X1334的尺寸。然后有问题去issues提哦~
      2019-08-19
      回复
    • 侯衍超
      侯衍超
      2019-08-19回复TNT
      目前海报图宽度是750,由于图片数量是不固定的,所以海报图高度不固定。issues已经提了,https://github.com/Kujiale-Mobile/Painter/issues/151,麻烦看一下
      2019-08-19
      回复
    • TNT
      TNT
      2019-08-19回复侯衍超
      👌
      2019-08-19
      回复
  • 山海求经
    山海求经
    2019-08-13

    请问这个base64格式的图片可以绘制么?

    2019-08-13
    赞同
    回复
  • 粗茶淡饭
    粗茶淡饭
    2019-08-09

    感谢分享 厉害厉害

    2019-08-09
    赞同
    回复 1
    • TNT
      TNT
      2019-08-09
      我文章里有写了专门生成图片的代码片段,可以查看个人中心文章列表里查看到
      2019-08-09
      回复
  • 开水泡蒸馍
    开水泡蒸馍
    2019-07-13

    支持表格生成图片吗?

    2019-07-13
    赞同
    回复
  • 开水泡蒸馍
    开水泡蒸馍
    2019-07-12

    表格可以生成图片吗?

    2019-07-12
    赞同
    回复

正在加载...

登录 后发表内容