跳到主要内容

在小程序中使用 Konva

先说结论:Konva 不能直接在微信小程序里运行,其他各家小程序也一样。

Konva 创建任何画布都走 Konva.Util.createCanvasElement(),它的第一步是检查浏览器环境, 然后调用 document.createElement('canvas')。小程序的逻辑层没有 document, 所以连 new Konva.Stage() 这一步都过不去。本站在同样没有 DOM 的 Node.js 里实测, 导入 konva 和创建 Konva.Rect 都能成功,但一创建舞台就抛出:

Konva.js unsupported environment.

Looks like you are trying to use Konva.js in Node.js environment (or in a Web Worker),
because "document" object is undefined.

这句提示里给出的 konva/canvas-backend 是给 Node.js 用的 node-canvas 原生模块,小程序里同样装不了。

用法​

实际可行的路线有三条。

1. <web-view> 内嵌 H5 页面。 把画布功能做成一个普通的网页,小程序里用 <web-view> 打开:

<!-- pages/editor/editor.wxml -->
<web-view src="https://your-domain.com/editor?id={{id}}"></web-view>

H5 页面里照常 import Konva from 'konva',功能不受任何限制。 H5 与小程序之间的通信需要在 H5 里引入微信 JS-SDK: 用 wx.miniProgram.navigateTo / redirectTo 把结果带参数传回小程序页面; wx.miniProgram.postMessage 发出的消息不会立即送达,只在小程序后退、组件销毁、分享等 特定时机才触发 <web-view> 的 message 事件,不适合做实时交互。具体行为以微信官方文档为准。

2. uni-app。 编译到 H5 时就是普通网页,Konva 正常可用。 编译到 App 时,可以把画布代码放进 renderjs 模块——它运行在视图层的 WebView 里,有完整的 DOM。 编译到各家小程序时不可用,原因同上,renderjs 也不支持小程序端。

<!-- 仅 H5 与 App 端生效 -->
<script module="konvaView" lang="renderjs">
import Konva from 'konva';

export default {
mounted() {
const stage = new Konva.Stage({ container: 'konva-box', width: 300, height: 300 });
// ...
},
};
</script>

3. Taro。 情况与 uni-app 一样:H5 端可用,小程序端不可用。

如果必须在小程序原生页面里画,就只能改用小程序的 Canvas 2D 接口(<canvas type="2d">), 等于放弃 Konva、自己实现图形对象和交互。

与其他方案的取舍​

web-view 是功能最完整的一条:Konva 的全部能力、现成的编辑器代码都能直接复用, 同一套页面还能在浏览器、App 里跑。代价有三:需要在小程序管理后台配置业务域名; 个人主体的小程序不能使用 <web-view>(以微信官方文档为准); 打开时要多加载一次 H5 页面,首屏比原生页面慢,与小程序的通信也只能靠跳转和延迟送达的消息。

原生 Canvas 2D 的性能和体验最好,也不受主体类型限制。但 Konva 帮你做的事—— 图形对象模型、命中检测、拖拽、Transformer、分层重绘、序列化——都要自己重新实现。 只画静态图表、海报合成这类没有交互的场景,原生接口足够; 有选中、拖拽、缩放旋转的编辑器,自己实现的成本通常远高于 web-view 带来的不便。

判断方法:交互复杂、且可以接受 web-view 的限制,选 web-view; 主体是个人、或者页面必须是原生页面,而交互又简单,选原生 Canvas 2D; 交互复杂又必须原生,考虑面向小程序设计的图形库,不要试图把 Konva 硬塞进去。

常见问题​

有没有 Konva 的小程序适配版?​

Konva 官方没有小程序版本。社区里有过一些通过伪造 document、替换画布创建函数来适配的尝试, 但事件系统、图片加载、离屏画布都要逐一对接,大多停留在很旧的 Konva 版本上。 采用前务必确认它的维护状态和对应的 Konva 版本,否则本站和官方文档的写法对它都不适用。

web-view 里的 Konva 性能会差吗?​

和在手机浏览器里打开同一个网页基本同级,没有额外的性能损失。 需要注意的是移动端的画布内存上限,图层多、屏幕像素比高时容易白屏, 估算方法与解决办法见移动端画布内存上限。

能不能只在小程序里用 Konva 做计算,不画图?​

不涉及画布的部分可以。在没有 DOM 的环境里,Konva.Transform 的矩阵运算、 Konva.Util 里的颜色转换等纯计算函数都能用(本站在 Node.js 里实测),但任何需要画布的操作—— 创建舞台和图层、导出图片,甚至创建 Konva.Text(它在构造时就要测量文字)——都会抛出同样的错误。 需要在服务端而不是小程序里生成图片的话,见在 Node.js 中使用 Konva。