更新记录
1.0.0(2021-03-24) 下载此版本
1.新增项目 2.本插件底层是基于Kujiale-Mobile/Painter(github地址:https://github.com/Kujiale-Mobile/Painter)插件生成; 3.在Kujiale-Mobile/Painter的基础上通过zhangdaren开源的uni-app转换器(github地址:https://github.com/zhangdaren/miniprogram-to-uniapp)转换成uniApp通用组件,并加以完善; 4.通过转换之后,免去Kujiale-Mobile/Painter复杂的使用过程,和非微信小程序端报错的问题; 5.使用方法参考Kujiale-Mobile/Painter(github地址:https://github.com/Kujiale-Mobile/Painter);
平台兼容性
Vue2 | Vue3 |
---|---|
√ | × |
App | 快应用 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节小程序 | QQ小程序 |
---|---|---|---|---|---|---|
HBuilderX 3.1.6 app-vue app-nvue | √ | √ | √ | √ | √ | √ |
钉钉小程序 | 快手小程序 | 飞书小程序 | 京东小程序 |
---|---|---|---|
× | × | × | × |
H5-Safari | Android Browser | 微信浏览器(Android) | QQ浏览器(Android) | Chrome | IE | Edge | Firefox | PC-Safari |
---|---|---|---|---|---|---|---|---|
√ | × | × | × | × | × | × | × | × |
vue-painter 2.0
使用简介
- 本插件底层是基于Kujiale-Mobile/Painter(github地址:https://github.com/Kujiale-Mobile/Painter)插件生成;
- 在Kujiale-Mobile/Painter的基础上通过zhangdaren开源的uni-app转换器(github地址:https://github.com/zhangdaren/miniprogram-to-uniapp)转换成uniApp通用组件,并加以完善;
- 通过转换之后,免去Kujiale-Mobile/Painter复杂的使用过程,和非微信小程序端报错的问题;
画家计划
想到小程序中有如此大量的生成图片需求,而 Canvas 生成方法又是如此难用和坑爹(有关小程序的坑,可看 https://github.com/Kujiale-Mobile/MP-Keng )。我们就想到可不可以做一款可以很方便生成图片,并且还能屏蔽掉直接使用 Canvas 的一些坑的库呢?对此我们发起了 “画家计划
— 通过 json 数据形式,来进行动态渲染并绘制出图片”。 Painter 库的整体架构如下:
首先,我们定义了一套绘图 JSON 规范,开发者可以根据需求构建生成图片的 Palette(调色板),然后在程序运行过程中把调色板传入给 Painter(画家)。Painter 会调用 Pen(画笔),根据 Palette 内容绘制出对应的图片后返回。
经过了一段时间的进步,painter 在大家的建议与贡献下得到了长足的成长。我们感谢各位使用者在这个过程中对 painter 的支持和帮助,这也是我们不断完善 painter 的最大动力。我们将为大家介绍 painter 的新能力,并明确下一阶段的迭代目标。
Painter 的优势
- 功能全,支持文本、图片、矩形、qrcode 类型的 view 绘制
- 布局全,支持多种布局方式,如 align(对齐方式)、rotate(旋转)
- 支持圆角,其中图片,矩形,和整个画布支持 borderRadius 来设置圆角
- 支持边框,同时支持 solid、dashed、dotted 三种类型
- 支持渐变色,包括线性渐变与径向渐变。
- 支持 box-shadow 和 text-shadow,统一使用 shadow 表示。
- 支持文字背景、获取宽度、主动换行
- 支持图片 mode
- 支持元素的相对定位方法
- 杠杠的性能优化,我们对网络素材图片加载实现了一套 LRU 存储机制,不用重复下载素材图片。
- 杠杠的容错,因为某些特殊情况会导致 Canvas 绘图不完整。我们对此加入了对结果图片进行检测机制,如果绘图出错会进行重绘。
- 生成的图片支持分辨率调节
- 支持使用拖动等操作动态编辑绘制内容
TODO
- [x] canvas2d 接口支持
- [ ] base64 图片支持 测试版本
- [ ] node 端服务版的 painter
- [ ] line-space 属性支持
- [ ] 三角形等常用图形的支持
- [ ] painter“插件” —— 支持使用者通过少量代码传入自行拓展 painter 能力
painter 的 “canvas2d 版本”与“base64 支持”正处于测试状态,可以在上方测试版本处链接获取对应版本,欢迎各位在实际体验后向我们反馈存在的问题,并给出宝贵的改进经验。你的支持将帮助 painter 做的更好
How To Use
快速开始
-
引入代码
下载vue-painter插件,拷贝到项目components目录
-
作为自定义组件引入,注意目录为第一步引入的代码所在目录
import painter from '@/components/dc_hiro-painter/painter.vue' export default { components:{painter}, }
-
组件接收
palette
字段作为画图数据的数据源, 图案数据以 json 形式存在,推荐使用“皮肤模板”的方法进行传递,示例代码如下:<painter palette="{{data}}" bind:imgOK="onImgOK" />
你可以通过设置 widthPixels 来强制指定生成的图片的像素宽度,否则,会根据你画布中设置的大小来动态调节,比如你用了 rpx,则在 iphone 6 上会生成 0.5 倍像素的图片。由于 canvas 绘制的图片像素直接由 Canvas 本身大小决定,此处通过同比例放大整个画布来实现对最后生成的图片大小的调节。
<painter customStyle='position: absolute; left: -9999rpx;' palette="{{template}}" bind:imgOK="onImgOK" widthPixels="1000"/>
-
数据传入后,则会自动进行绘图。绘图完成后,你可以通过绑定 imgOK 或 imgErr 事件来获得成功后的图片 或失败的原因。
bind:imgOK="onImgOK" bind:imgErr="onImgErr" onImgOK(e) { 其中 e.detail.path 为生成的图片路径 },
-
你也可以通过使用
dancePalette
、action
等字段开启 painter 的高阶用法。具体使用方式将会在下方有详细描述。在新版 painter 中,静态模版默认相对 painter 本身 left: -9999px 。因此正常情况下使用 painter 时出现在页面上的都是动态模版。如果希望禁止用户的操作,可以按照使用静态模版的做法,只传 palette 属性即可。
组件文档
属性 | 类型 | 说明 | 必填 | 默认值 |
---|---|---|---|---|
customStyle | string | canvas 的自定义样式 | 否 | |
palette | IPalette | 静态模版,具体规范下文有详细介绍 | 否 | |
scaleRatio | number | 缩放比,会在传入的 palette 中统一乘以该缩放比 | 否 | 1 |
widthPixels | number | 生成的图片的像素宽度,如不传则根据模版动态生成 | 否 | 0 |
dirty | boolean | 是否启用脏检查 | 否 | false |
LRU | boolean | 是否开启 LRU 机制 | 否 | false |
dancePalette | IPalette | 动态模版,规范同静态模版 | 否 | |
customActionStyle | ICustomActionStyle | 选择框、缩放图标、删除图标的自定义样式与图片 | 否 | |
action | IView | 动态编辑内容,用于刷新动态模版 | 否 | |
disableAction | boolean | 禁止动态编辑操作 | 否 | false |
clearActionBox | boolean | 清除动态编辑框 | 否 | false |
imgErr | function | 图片生成失败,可以从 e.detail.error 获取错误信息 | 否 | |
imgOk | function | 图片生成成功,可以从 e.detail.path 获取生成的图片路径 | 否 | |
viewUpdate | function | 动态模版, view 被更新,可从 e.detail.view 获取更新的 view | 否 | |
viewClicked | function | 动态模版, view 被选中, 可从 e.detail.view 获取点击的 view,如为空,则是选中背景 | 否 | |
touchEnd | function | 动态模版,触碰结束。只有 view,代表触碰的对象;包含 view、type、index,代表点击了删除 icon; | 否 | |
didShow | function | 动态模版,绘制结束时触发 | 否 | |
use2D | boolean | 是否使用 canvas2d 接口(注意!使用 use2D 就无法使用 dancePalette 与 action) | 否 | false |
interface IView {
type: "rect" | "text" | "image" | "qrcode";
text?: string;
url?: string;
id?: string;
/** 事实上painter中view的css属性并不完全与CSSProperties一致。 */
/** 有一些属性painter并不支持,而当你需要开启一些“高级”能力时,属性的使用方式也与css规范不一致。 */
/** 具体的区别我们将在下方对应的view介绍中详细讲解,在这里使用CSSProperties仅仅是为了让你享受代码提示 */
css: CSSProperties;
}
interface IPalette {
background: string; // 整个模版的背景,支持网络图片的链接、纯色和渐变色
width: string;
height: string;
borderRadius: string;
views: Array<IView>;
}
interface ICustomActionStyle {
border: string; // 动态编辑选择框的边框样式
scale: {
textIcon: string; // 文字view所使用的缩放图标图片
imageIcon: string; // 图片view所使用的缩放图标图片
};
delete: {
icon: string; // 删除图标图片
};
}
Palette 规范
如你使用 wxss + wxml 规范进行绘制一样,Painter 需要根据一定的规范来进行图片绘制。当然 Painter 的绘制规范要比 wxml 简单很多。这部分的例子都是基于 palette
属性实现的静态模版
调色板属性
一个调色板首先需要给予一些整体属性
background: 可以是颜色值,也可以为网络图片的链接,默认为白色,支持渐变色
width: 宽度
height: 高度
borderRadius: 边框的圆角(该属性也同样适用于子 view)
views: 里面承载子 view
View 属性
当我们把整体的调色板属性构建起来后,里面就可以添加子 View 来进行绘制了。
type | 内容 | description | 自有 css |
---|---|---|---|
image | url | 表示图片资源的地址,本地或网络 | 见 image 小节 |
text | text | 文本的内容 | 见 text 小节 |
rect | 无 | 矩形 | color: 颜色,支持渐变色 |
qrcode | content | 画二维码 | background: 背景颜色(默认为透明色)color: 二维码颜色(默认黑色) |
image
Painter 的 image 可以设置成本地图片或者网络图片,注意本地图片请使用绝对路径。并且如果未设置 image 的长宽,则长宽的属性值会默认设为 auto。若长宽均为 auto 则会使用图片本身的长宽来布局,大小为图片的像素值除以 pixelRatio 。
属性名称 | 说明 | 默认值 |
---|---|---|
width | image 的宽度 | auto |
height | image 的高度 | auto |
mode | 图片裁剪、缩放的模式 | aspectFill |
scaleToFill:不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素
aspectFill:保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
注:mode 属性和小程序 image 的 mode 属性功能一致,只是支持的类型只有两种,且默认值不同。 当 width 或 height 属性设置为 auto 时,mode 属性失效
例子代码(点击展开)
```javascript export default class ImageExample { palette() { return { width: "654rpx", height: "1000rpx", background: "#eee", views: [ { type: "image", url: "/palette/sky.jpg", }, { type: "text", text: "未设置height、width时", css: { right: "0rpx", top: "60rpx", fontSize: "30rpx", }, }, { type: "image", url: "/palette/sky.jpg", css: { width: "200rpx", height: "200rpx", top: "230rpx", }, }, { type: "text", text: "mode: 'aspectFill' 或 无", css: { left: "210rpx", fontSize: "30rpx", top: "290rpx", }, }, { type: "image", url: "/palette/sky.jpg", css: { width: "200rpx", height: "200rpx", mode: "scaleToFill", top: "500rpx", }, }, { type: "text", text: "mode: 'scaleToFill'", css: { left: "210rpx", top: "560rpx", fontSize: "30rpx", }, }, { type: "image", url: "/palette/sky.jpg", css: { width: "200rpx", height: "auto", top: "750rpx", }, }, { type: "text", text: "设置height为auto", css: { left: "210rpx", top: "780rpx", fontSize: "30rpx", }, }, ], }; } } ```
text
因为 text 的特殊性,此处对 text 进行单独说明。
属性名称 | 说明 | 默认值 |
---|---|---|
width | text 的宽度 | |
height | text 的高度 | |
fontSize | 字体大小 | 20rpx |
color | 字体颜色 | black |
maxLines | 最大行数 | 不限,根据 width 来 |
lineHeight | 行高(上下两行文字 baseline 的距离) | fontSize 大小 |
fontWeight | 字体粗细。 | normal |
textDecoration | 文本修饰,支持 underline、 overline、 line-through,也可组合使用 | 无效果 |
textStyle | fill: 填充样式,stroke:镂空样式 | fill |
background | 文字背景颜色 | 无 |
padding | 文字背景颜色边际与文字间距 | 0rpx |
textAlign | 文字的对齐方式,分为 left, center, right,view 的对齐方式请看 align 属性 | left |
当文字设置 width 属性后,则文字布局的最大宽度不会超过该 width 。如果内容超过 width,则会进行换行,如果此时未设置 maxLines 属性,则会把所有内容进行换行处理,行数由内容和 width 决定。如果此时设置了 maxLines 属性,则最大展示所设置的行数,如果还有多余内容未展示出来,则后面会带上 ... 。
关于 fontFamily 属性,有一点需要澄清,最开始文档中写的可以通过 wx.loadFontFace 来加载自定义字体,是不严谨的。事实上,原版 canvas 接口不支持自定义字体。而从 2.13.0 版本基础库开始,canvas2d 版本的接口开始支持自定义字体。我们找到了如下问答作为依据: 问题链接。
- 以下用个例子说下上述几个属性的用法
例子代码(点击展开)
```javascript export default class LastMayday { palette() { return { width: "654rpx", height: "700rpx", background: "#eee", views: [ _textDecoration("overline", 0), _textDecoration("underline", 1), _textDecoration("line-through", 2), _textDecoration("overline underline line-through", 3, "red"), { type: "text", text: "fontWeight: 'bold'", css: [ { top: `${startTop + 4 * gapSize}rpx`, fontWeight: "bold", }, common, ], }, { type: "text", text: "我是把width设置为300rpx后,我就换行了", css: [ { top: `${startTop + 5 * gapSize}rpx`, width: "400rpx", }, common, ], }, { type: "text", text: "我设置了maxLines为1,看看会产生什么效果", css: [ { top: `${startTop + 7 * gapSize}rpx`, width: "400rpx", maxLines: 1, }, common, ], }, { type: "text", text: "textStyle: 'stroke'", css: [ { top: `${startTop + 8 * gapSize}rpx`, textStyle: "stroke", fontWeight: "bold", }, common, ], }, ], }; } } const startTop = 50; const gapSize = 70; const common = { left: "20rpx", fontSize: "40rpx", }; function _textDecoration(decoration, index, color) { return { type: "text", text: decoration, css: [ { top: `${startTop + index * gapSize}rpx`, color: color, textDecoration: decoration, }, common, ], }; } ```
布局属性
以上 View ,除去自己拥有的特别属性外,还有以下的通用布局属性
属性 | 说明 | 默认 |
---|---|---|
rotate | 旋转,按照顺时针旋转的度数 | 不旋转 |
width、height | view 的宽度和高度,其中 image 和 text 可不设置 | |
top、right、bottom、left | 如 css 中为 absolute 布局时的作用,可为 负值 | 默认 top 和 left 为 0 |
相对布局方法
很多人有获得文本宽度的需求,因为文本宽度随着字数不同而动态变化,如果想在文本后面加个图标,那么我们就需要获得文本宽度。Painter 的解决方案如下:
1,首先你需要为检测长度的文本添加一个 id。如下
{
id: 'my-text-id',
type: 'text',
2,然后在后面的 view 中,你可以在 left、right、top属性中使用这个id。如下
left: ['10rpx', 'my-text-id', 比例]
表示布局在距离左边(10rpx + 该text文本宽度 * 比例) 的距离,比例默认为 1,可省去,你也可以使用负数或小数来做计算,最终的 left 会加上文本宽度乘以该数的值。
注意:
- 比例一定为一个 number
- 获得的长度为 view 自身的尺寸,而非该 view 到对应边的 距离 + 自身尺寸
如果想获得高度,top 也支持上述用法,并且除文本外,你可以对任何 view 设置一个 id,然后使用上述方法进行相对布局。
注:相对布局的那个 view 代码一定需要在被相对的 view 的下面。
border 类型
属性 | 说明 | 默认 |
---|---|---|
borderRadius | 边界圆角程度,如果是正方形布局,该属性为一半宽或高时,则为圆形 | 0 |
borderWidth | 边界宽度,外边界 | 必设值,否则无边框效果 |
borderColor | 边框颜色 | black |
borderStyle | 边框样式,支持 dashed、dotted、solid | solid |
align
Painter 的 align 类型与 css 中的 align 有些许不同。在 Painter 中 align 表示 view 本身的对齐方式,而不像 css 中表示对其子 view 的操作。align 可以作用在 Painter 支持的所有 view 上。它以设置的 left、top、right、bottom 的位置为基准,然后做不同的对齐操作。并且 align 在文字多行情况下,会影响多行文字的对齐方式。
注意:如果布局使用了 right 确定位置,则该 view 会默认右对齐布局,但此时文字还是从左边绘制。
例子代码(点击展开)
```javascript { width: '654rpx', height: '600rpx', background: '#eee', views: [ { type: 'rect', css: { top: '40rpx', left: '327rpx', color: 'rgba(255, 0, 0, 0.5)', width: '5rpx', height: '500rpx', }, }, { type: 'image', url: '/palette/avatar.jpg', css: { top: '40rpx', left: '327rpx', width: '100rpx', height: '100rpx', }, }, { type: 'qrcode', content: '/palette/avatar.jpg', css: { top: '180rpx', left: '327rpx', width: '120rpx', height: '120rpx', }, }, { type: 'text', text: "align: 'left' 或者不写", css: { top: '320rpx', left: '327rpx', fontSize: '30rpx', }, }, { type: 'text', text: "align: 'right'", css: { top: '370rpx', left: '327rpx', align: 'right', fontSize: '30rpx', }, }, { type: 'text', text: "align: 'center'", css: { top: '420rpx', left: '327rpx', align: 'center', fontSize: '30rpx', }, }, { type: 'text', text: "在多行的情况下,align 会影响内部 text 的对齐,比如这边设置 align: 'center'", css: { top: '480rpx', right: '327rpx', width: '400rpx', align: 'center', fontSize: '30rpx', }, }, ], } ```
CSS3 支持
shadow
Painter 中的 shadow 可以同时修饰 image、rect、text、qrcode 等 。在修饰 text 时则相当于 text-shadow;修饰 image 和 rect 时相当于 box-shadow;修饰 qrcode 时,则相当于二维码有效区域的投影。
使用方法:
shadow: 'h-shadow v-shadow blur color';
h-shadow: 必需。水平阴影的位置。允许负值。
v-shadow: 必需。垂直阴影的位置。允许负值。
blur: 必需。模糊的距离。
color: 必需。阴影的颜色。
例子代码(点击展开)
```javascript export default class ShadowExample { palette() { return { width: "654rpx", height: "400rpx", background: "#eee", views: [ { type: "image", url: "/palette/sky.jpg", css: { shadow: "10rpx 10rpx 5rpx #888888", }, }, { type: "rect", css: { width: "250rpx", height: "150rpx", right: "50rpx", top: "60rpx", shadow: "10rpx 10rpx 5rpx #888888", color: "linear-gradient(-135deg, #fedcba 0%, rgba(18, 52, 86, 1) 20%, #987 80%)", }, }, { type: "qrcode", content: "https://github.com/Kujiale-Mobile/Painter", css: { top: "230rpx", width: "120rpx", height: "120rpx", shadow: "10rpx 10rpx 5rpx #888888", }, }, { type: "text", text: "shadow: '10rpx 10rpx 5rpx #888888'", css: { left: "180rpx", fontSize: "30rpx", shadow: "10rpx 10rpx 5rpx #888888", top: "290rpx", }, }, ], }; } } ```
渐变色支持
你可以在画布的 background 属性或者 rect 的 color 属性中使用以下方式实现 css 3 的渐变色,其中 radial-gradient 渐变的圆心为 view 中点,半径为最长边,目前不支持自己设置。
{
background: linear-gradient(
-135deg,
blue 0%,
rgba(18, 52, 86, 1) 20%,
#987 80%
);
color: radial-gradient(rgba(0, 0, 0, 0) 5%, #0ff 15%, #f0f 60%);
}
!!!注意:颜色后面的百分比一定得写。
其他技巧
文字竖行显示
因为 Painter 支持换行符,所以我们可以配合向字符之间插入换行符来达到竖排显示的效果,并且我们还能自由控制是从左到右或从右到左,如下图所示。
例子代码(点击展开)
```javascript const text = "锄禾日当午汗滴禾下土谁知盘中餐粒粒皆辛苦"; export default class ImageExample { palette() { const views = []; let tmpText = ""; let index = 0; for (let i = 0; i < text.length; i++) { tmpText = `${tmpText}${text[i]}\n`; if (i % 5 === 4) { views.push({ type: "text", text: tmpText, css: { right: `${50 + index}rpx`, top: "60rpx", fontSize: "40rpx", lineHeight: "50rpx", }, }); index += 50; tmpText = ""; } } return { width: "654rpx", height: "500rpx", background: "#eee", views: views, }; } } ``` </details>
动态模版
使用方法
<painter
customStyle='margin-left: 40rpx; height: 1000rpx;'
palette="{{paintPallette}}"
bind:imgOK="onImgOK"
customActionStyle="{{customActionStyle}}"
dancePalette="{{template}}"
bind:touchEnd="touchEnd"
action="{{action}}"
/>
// ···
data: {
// ···
customActionStyle: {
border: {
borderColor: "#1A7AF8",
},
scale: {
textIcon: "/palette/switch.png",
imageIcon: "/palette/scale.png",
},
delete: {
icon: "/palette/close.png",
},
},
},
// ···
动态模版向用户提供了一个可供编辑的海报模版。在使用动态模版时,painter 默认支持用户对海报中 view 的拖动、缩放和删除操作,增加海报自由度。(了解更多关于动态模版)
customStyle、palette、imgOk 三个属性是旧版 painter 已存在的,使用方式并没有发生变化,因此不再赘述。(这里同时使用静态模版和动态模版,是为了在动态模版上编辑完毕后,通过静态模版生成一整张图片交给用户)
可以通过 customActionStyle 自定义操作 icon 与操作框的样式。通过 dancePalette,我们传入初始的模版,当后续有模版级别的刷新的时候,我们也是修改 dancePlette 的传入值。action 用于传入单个 view 级别的修改。若传入的 view 含 id,则将覆盖该 id 匹配的 view,若无 id,则默认覆盖当前选中的 view。可以通过 touchEnd 获取当前选中的 view 或是感知到用户的删除操作。
若是要使 view 可被缩放,需要在 css 中配置 scalable: true,而如果需要 view 可被删除,需要在 css 中配置 deletable: true,
拓展能力
通过动态模版能力拓展出的几种进阶用法:
- 动态更新 view 属性,如替换图片 url、修改文字、修改文字样式
效果展示(点击展开,多图预警)
初始状态 ![初始状态](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499189/C95F8D892B9D3699F71C65A6B104D0AE.jpg?x-oss-process=image/resize,w_200) 图片缩放、移动 ![图片缩放、移动](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499011/E5EE3DBDE555A053CCF8A6734409E4F9.jpg?x-oss-process=image/resize,w_200) 图片切换 ![图片切换](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499048/D593CB0BF382860058228702EEB16386.jpg?x-oss-process=image/resize,w_200) 图片裁剪(这里的裁剪是配合另一个库 CropperCore 实现的,painter 本身无法裁剪图片) ![图片裁剪](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499054/8B931E9628FEE5D67C3774096CB5F6B1.jpg?x-oss-process=image/resize,w_200) 文字选中 ![文字选中](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499617/D38D3DE8E92FB13D1656F745E4010584.jpg?x-oss-process=image/resize,w_200) 文字缩放 ![文字缩放](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499042/E5D70B678460DBC4DAB280AE6BF02956.jpg?x-oss-process=image/resize,w_200) 文字编辑 ![文字编辑](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499041/156FEFA0FCCD8C0C2F011A9071DEBAAC.jpg?x-oss-process=image/resize,w_200) 字号调节 ![字号调节](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499449/51516F4253AA68A6E85C558C994193A7.jpg?x-oss-process=image/resize,w_200) 文字颜色 ![文字颜色](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499252/FA70651AE9A80BD68EAFE1273204449B.jpg?x-oss-process=image/resize,w_200) 文字样式 ![文字样式](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499450/8F58A08A568287CBEE7993DF90469B81.jpg?x-oss-process=image/resize,w_200) 背景颜色 ![背景颜色](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499471/BD61462977BA8E65E02FBAEB98BD2D70.jpg?x-oss-process=image/resize,w_200) 新增文字 ![新增文字1](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499018/E8DD995983063961D05FBC77653EEB84.jpg?x-oss-process=image/resize,w_200) 新增文字 ![新增文字](https://qhstaticssl.kujiale.com/newt/100082/image/jpeg/1601360499433/FF5B1F5DA3CA9A463ED844C0091C453C.jpg?x-oss-process=image/resize,w_200)- 撤销、恢复修改 在示例中,我们实现了简单的撤销恢复功能,大致思路为:在页面中维护 future 、 history 两个数组,分别记录需要恢复和需要撤销的变动,当作出修改操作,则在修改前先将该 view 的当前状态传入 history,同时清空 future。若是点击撤销,则将点击时刻的 view 传入 future,再用 history 顶部的 view 更新模版。若点击恢复,则将点击时刻的 view 传入 history,在用 future 顶部的 view 更新模版。
示例代码(点击展开)
```javascript // ··· onRevert() { const pre = this.history.pop(); if (!pre) { return; } // ··· this.future.push(pre); // ··· }, onRecover() { const fut = this.future.pop(); if (!fut) { return; } // ··· this.history.push(fut); // ··· }, touchEnd({ detail }) { // ··· this.history.push({ ...detail, }); // ··· this.future.length = 0; // ··· }, // ··· ```Tips(一定要看哦~)
1,目前 Painter 中支持两种尺寸单位,px 和 rpx,代表的意思和小程序中一致,此处就不多说。
2,目前子 view 的 css 属性支持 object 或 array。所以意味着,你可以把几个子 view 共用的 css 属性提取出来。做到让 Palette 更加简洁。
3,因为我们的 palette 是以 js 承载的 json,所以意味着你可以在每一个属性中很方便的加上自己的逻辑。也可以把某些属性单独提取出来,让多个 palette 共用,做到模块化。
4,如果你只希望获得一张生成的图片来展示,可以把 Painter 挪动到屏幕外进行绘制,绘制完后得到一张图片再进行展示,如下面这样。
<painter style="position:fixed;top:-9999rpx" palette="{{userInfoTemplate}}" bind:imgOK="onImgOK" />
举个栗子
{
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',
},
}
...
],
}
绘制效果如下