本仓库为 wxml-to-canvas 外部扩展渲染库(非侵入性,不改变原版API),可以更高效、快速地生成插件需要的数据。当海报中有需要循环的数据时,原版需要复杂的字符串拼接。而通过这个扩展,可以非常方便地做到循环渲染(有点类似与React)。
目前扩展的内容比较简单,大致包含三个部分:
- DOM树组合
- DOM树转换
- 各元素尺寸计算
以原生小程序为例:
将 /dist/wxml-to-canvas
复制到小程序项目的 components/
中
{
"usingComponents": {
// 页面中使用相对路径引入
"wxml-to-canvas": "../../components/wxml-to-canvas"
}
}
const {
el,
WTCUtils,
} = require('../../components/wxml-to-canvas/wtc'); // 注意:扩展库位于 wxml-to-canvas/wtc.js 内
Page({
data: {
src: '', // 用于存放生成的图片路径
size: null, // 用于存放容器尺寸
},
...
})
<view>
<wxml-to-canvas wx:if="{{size}}" class="widget" width="{{size.width}}" height="{{size.height}}"></wxml-to-canvas>
<button type="primary" style="margin: 1rem auto;" bindtap="extraImage">生成图片</button>
</view>
<view wx:if="{{src}}">
<image src="{{src}}" mode="widthFix" style="width: 100vw;" bindtap="viewImage"></image>
<button type="primary" style="margin: 1rem auto;" bindtap="saveImage">导出图片</button>
</view>
onLoad() {
// 先创建工具类实例,传入画布尺寸
this.utils = WTCUtils.create(750 * 1.2, 889 * 1.2);
// 将尺寸注入到页面中
this.setData({
size: this.utils.getSize(),
}, () => {
// 需要等待页面渲染完成,否则找不到 canvas
setTimeout(() => {
// 第四步:构建。
this.build();
}, 100);
});
}
build() {
// 通过小程序API获取组件实例
this.widget = this.selectComponent('.widget');
// 将组件注入到工具类实例中
this.utils.setWidget(this.widget);
// 获取容器尺寸
const size = this.utils.getSize(); // {width: number, height: number}
// 构建 DOM 树
const dom = el('view', { // 根容器必须为 view
class: 'container',
style: {
...size,
backgroundColor: '#fff',
},
children: [
(() => {
const backSize = this.utils.widthFix(1152, 1152, 0.26);
// 定义图片
return el('image', {
class: 'qiaFanImage',
// 图片的 src 属性为必传
src: 'https://cloud-minapp-37929.cloud.ifanrusercontent.com/1kflAf6K5B5D5ucV.jpg',
style: {
position: 'absolute', // 建议 position 统一传 'absolute'
left: this.utils.getScaleWidth(55 / size.width),
top: this.utils.getScaleHeight(600 / size.height),
...backSize,
},
})
})(),
(() => {
// 定义封面图片
return el('image', {
class: 'coverImage',
src: 'https://cloud-minapp-37929.cloud.ifanrusercontent.com/1kflb1WtHktkL6L0.png',
style: {
position: 'absolute',
top: 0,
left: 0,
...size,
},
})
})(),
(() => {
// 定义文字
return el('text', {
class: 'heiHei',
text: '窝窝头,一块钱四个~', // text 必传
style: {
position: 'absolute',
left: this.utils.getScaleWidth(20 / size.width),
top: this.utils.getScaleHeight(450 / size.height),
color: '#fff',
fontSize: 26,
},
})
})(),
]
});
// 将DOM树转化成插件可读的数据
const metadata = this.utils.covertElToMetadata(dom);
// 直接将数据喂给插件即可
const p1 = this.widget.renderToCanvas(metadata);
p1.then((res) => {
console.log('container', res);
});
}
extraImage() {
wx.showLoading({title: '图片生成中'}).then(() => {
const p2 = this.widget.canvasToTempFilePath({quality: 0.6, fileType: 'jpg', scale: 1.5});
p2.then(res => {
// 将生成的图片地址注入页面
this.setData({ src: res.tempFilePath });
wx.hideLoading();
});
});
}
- tagName 目前官方仅支持 'view' | 'image' | 'text'
WTCElement
export interface WTCElement {
tagName?: string; // 扩展库自用,请忽略
class: string; // 必传,且保证唯一
style?: WTCCSSStyleDeclaration; // 遵守原插件样式定义
children?: (WTCElement | null)[]; // 子元素数组
src?: string; // image 时传入
text?: string; // text 时传入
}
去看看 原插件样式定义
- 需要注意的是,原版说每个元素必传
width
和height
,现在text
已经不需要了,我会默认计算文字的宽高。
- containerWidth 默认为屏幕宽度
- containerHeight 默认为屏幕高度
- widget 官方插件实例,必须传入,否则无法计算字体宽度
- WTCElement 构建完的Element对象
- deep 深度,扩展库自用,勿传
WTCMetadata
export interface WTCMetadata {
wxml: string; // 插件需要的 wxml
style: { [key: string]: WTCCSSStyleDeclaration }; // 插件需要的样式
width: number; // 容器宽度
height: number; // 容器高度
}
width
容器宽度height
容器高度
WTCUtils#widthFix
(originalWidth: number, originalHeight: number, scale = 1): {width
: number; height
: number;}
- originalWidth 原始宽度
- originalHeight 原始高度
- scale 缩放比例
width
(与容器等宽) * 缩放比例height
(与容器等宽的同时,按原始宽高比,等比缩放的高度) * 缩放比例
WTCUtils#heightFix
(originalWidth: number, originalHeight: number, scale = 1): {width
: number; height
: number;}
- originalWidth 原始宽度
- originalHeight 原始高度
- scale 缩放比例
width
(与容器等高的同时,按原始宽高比,等比缩放的宽度) * 缩放比例height
(与容器等高) * 缩放比例
- scale 缩放比例
- scale 缩放比例
- text 字符串
我在原有style的基础上增加了一个新的属性 textLine
,顾名思义,这个属性用于多行文本,比如 textLine 传入 2 时,文本元素的高度 = 文字高度 * 2。
- options.
fileType
: 'jpg' | 'png' - options.
quality
: (0, 1] // 目前仅对 jpg 有效 - options.
scale
: 1 // 输出图片的缩放比例,默认为 1
/dist/wxml-to-canvas
为合成版组件,可以独立使用。/examples
存放了一些使用示例(目前只完善了原生小程序)
- 1.0.0 版本发布
- 完善微信原生小程序示例
- 完善Taro示例
- 完善UniApp示例
- 优化渲染逻辑,使图片可以自动设置原始宽高
- @jiangyh 感谢
[隔壁小甜]
第一时间试用并给予支持