我们经常会遇上动态生成海报的需求,而在小程序中,生成图片非Canvas莫属。但是在实际工作当中,为了追求效率,我们会不可避免地去使用一些JS插件,而 wxml-to-canvas
就是一款官方推荐且非常优秀的插件,它可以轻松地帮你将HTML代码转换成Canvas,进而生成可保存分享的图片。
但是wxml-to-canvas
是通过静态模板和样式绘制 canvas ,进而导出图片,需要单独写一份静态模板用于编译,对于很多场景还是有些限制,比如有时需要将图文混排的富文本内容生成分享图,对于这种长度不定,内容动态变化的图片生成需求,直接利用官方的canvas接口绘制是十分困难的,包括但不限于文字换行、表情文字图片混排、文字加粗、子标题等元素都需要一一绘制
我们的目标是实现一个通过wxml
节点标记,收集元素从而进行编译转换,仅依赖wxml
直出需要绘制的canvas进而快速实现图片分享,为此学习了 wxml2canvas
npm包,实现了基础功能的wxml2canvas
- 此文暂不讨论图片类型的
wxml
转canvas
先看结果🌰
我们针对简单的demo进行处理,包含了对块级元素
、行内元素
、背景色
、等简单样式的转换,达到 wxml
->canvas
->image
的一次性处理,且不需要重复书写静态代码模板进行编译
![](https://raw.githubusercontent.com/blazer233/wxml2canvas/func/simple/show.png)
下面让我们一步步探求如何实现这个tiny版的wxml2canvas
实现
小程序提供了如下特性,可供我们便捷使用:
- measureText接口能直接测量出文本的宽度;
- SelectorQuery可以查询到节点对应的computedStyle。
同时小程序也存在一些弊端,比如:
- canvas属于原生组件,在移动端会置于最顶层;
- 通过SelectorQuery只能拿到节点的style,而无法获取文本节点的内容
所以我们第一步获取元素就面临两个问题:
1.如何获取需要转成canvas的元素
2.如何拿到获取元素的对应属性(样式、节点、内容…)
当获取到待收集的元素后,就可以将元素绘制到指定的canvas上,也就实现了wxml2canvas
所以初始化时,需要传入如下参数
/**
* element:需要渲染的canvas节点
* class:查找所有类名为exc-c的节点,并进行加入绘制队列
* limit:限定相对位置
*
**/
wxml2Canvas({element: "over-canvas",options: {class: ".exc-c",limit: ".limit-r",},
})
在wxml中需要绘制的元素需添加 exc-c
类名,方便对元素进行查找,并且如果需要限定相对位置,也需要在父级添加 limit-r
类名,例如,一个文本的位置(left, top) = (50, 80),class为panel的节点的位置为(left, top) = (20, 40),则文本canvas上实际绘制的位置(x, y) = (50 - 20, 80 -40) = (30, 40)。如果不传入limit,则以实际的位置(x, y) = (50, 80) 绘制
对于 wxml
而言,如有需要渲染的文本,也需要将文本内容通过 data-text="xxx"
属性的方式进行挂载,因为 SelectorQuery
无法获取文本节点的内容但是可以获取到节点的 dataset
属性,从而拿到文本内容
wxml
代码如下:
<view class="content">Wxml:</view><view class="-box limit-r"><view class="-line exc-c" data-type="inline-text" data-text="这是{
{txt}}">这是{
{txt}}</view><view class="-line -blue exc-c" data-type="inline-text" data-text="这是蓝色行内文字试试">这是蓝色行内文字试试</view><view class&