MCPcopy Index your code
hub / github.com/manycore-maas/Painter

github.com/manycore-maas/Painter @2.2.2

repository ↗ · DeepWiki ↗ · release 2.2.2 ↗ · + Follow
175 symbols 308 edges 17 files 5 documented · 3%
README

Painter 2.0

画家计划

想到小程序中有如此大量的生成图片需求,而 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 接口支持
  • [x] base64 图片支持
  • [x] calc 支持
  • [ ] node 端服务版的 painter
  • [ ] line-space 属性支持
  • [ ] 三角形等常用图形的支持
  • [ ] painter“插件” —— 支持使用者通过少量代码传入自行拓展 painter 能力

painter 的 “canvas2d 版本”与“base64 支持”正处于测试状态,可以在上方测试版本处链接获取对应版本,欢迎各位在实际体验后向我们反馈存在的问题,并给出宝贵的改进经验。你的支持将帮助 painter 做的更好

How To Use

运行例子

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

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

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

快速开始

mpvue 的使用方法请移步 mpvue 接入方案

taro 的使用方法请参考 Taro 接入方案 painter 已发布 taro 版本的 npm 包mina-painter

  1. 引入代码

Painter 的核心代码在另一个 repo 中,https://github.com/Kujiale-Mobile/PainterCore.git 。你可以通过 submodule 的方式进行库的引入。有关 submodule 的用法可自行 Google。

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

  1. 作为自定义组件引入,注意目录为第一步引入的代码所在目录

json "usingComponents":{ "painter":"/components/painter/painter" }

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

xml <painter palette="{{data}}" bind:imgOK="onImgOK" />

你可以通过设置 widthPixels 来强制指定生成的图片的像素宽度,否则,会根据你画布中设置的大小来动态调节,比如你用了 rpx,则在 iphone 6 上会生成 0.5 倍像素的图片。由于 canvas 绘制的图片像素直接由 Canvas 本身大小决定,此处通过同比例放大整个画布来实现对最后生成的图片大小的调节。

xml <painter customStyle='position: absolute; left: -9999rpx;' palette="{{template}}" bind:imgOK="onImgOK" widthPixels="1000"/>

  1. 数据传入后,则会自动进行绘图。绘图完成后,你可以通过绑定 imgOK 或 imgErr 事件来获得成功后的图片 或失败的原因。

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

onImgOK(e) { 其中 e.detail.path 为生成的图片路径 }, ```

  1. 你也可以通过使用 dancePaletteaction 等字段开启 painter 的高阶用法。具体使用方式将会在下方有详细描述。在新版 painter 中,静态模版默认相对 painter 本身 left: -9999px 。因此正常情况下使用 painter 时出现在页面上的都是动态模版。如果希望禁止用户的操作,可以按照使用静态模版的做法,只传 palette 属性即可。

组件文档

属性 类型 说明 必填 默认值
customStyle string canvas 的自定义样式
palette IPalette 静态模版,具体规范下文有详细介绍
scaleRatio number 缩放比,会在传入的 palette 中统一乘以该缩放比,作用和 widthPixels 类似,所以不要同时使用 1
widthPixels number 生成的图片的像素宽度,如不传则根据模版动态生成
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 属性失效

例子代码(点击展开)

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 版本的接口开始支持自定义字体。我们找到了如下问答作为依据: 问题链接

  • 以下用个例子说下上述几个属性的用法

例子代码(点击展开)

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,
    ],
  };
}

Core symbols most depended-on inside this repo

setmask
called by 23
components/painter/lib/qrcode.js
ismasked
called by 9
components/painter/lib/qrcode.js
moveTo
called by 9
components/painter/lib/wx-canvas.js
safe_add
called by 9
components/painter/lib/sha1.js
lineTo
called by 8
components/painter/lib/wx-canvas.js
paint
called by 8
components/painter/lib/pen.js
save
called by 7
components/painter/lib/wx-canvas.js
restore
called by 7
components/painter/lib/wx-canvas.js

Shape

Method 86
Function 73
Class 16

Languages

TypeScript100%

Modules by API surface

components/painter/lib/wx-canvas.js63 symbols
components/painter/painter.js25 symbols
components/painter/lib/pen.js19 symbols
components/painter/lib/downloader.js16 symbols
components/painter/lib/qrcode.js12 symbols
components/painter/lib/sha1.js8 symbols
palette/card.js6 symbols
pages/example/example.js5 symbols
components/painter/lib/util.js4 symbols
components/painter/lib/gradient.js4 symbols
palette/text-example.js3 symbols
palette/shadow-example.js3 symbols

For agents

$ claude mcp add Painter \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact