从 G6 3.0 正式对外放出 beta 版以来,询问量居高不下的问题就是:G6 是否还支持 html 类型的节点?这个问题,我们一直有思考,讨论,但是始终无法达成一致意见着手去做。
为什么考虑加 html 节点
相对于canvas,HTML存在很大优势:
- 节点上存在多个热区,需要监听多个部分的事件做交互的情况;
- 使用 html 布局可以很方便的实现文字居中,自动换行,内容溢出自动省略等;
- 用 css 伪类可以很方便的实现一些节点状态的样式切换;
- 节点结构比较复杂时,可以降低定制节点时间。
G6 中支持 html 节点的方案
html 置于canvas下层
在 G6 容器节点下创建一个 html 节点的容器,所有 html 节点置于 canvas 下方。结构如下:
<div>
<div id="g6-html-container">
<div class="g6-node">...</div>
<div class="g6-node">...</div>
</div>
<canvas />
</div>
优点:
- 能支持html节点外观方面的各种features;
- 实现便捷,支持视口的各种操作。
缺点:
- 缺少 html 事件机制;
- 有 G6 内置事件事件捕获与实际节点错位的可能性。
html 在 canvas 上层
在canvas之后创建一个个节点,所有html 节点在 canvas 上方,结构如下:
<div>
<canvas />
<div class="g6-node">...</div>
<div class="g6-node">...</div>
</div>
优点:
- 能支持 html 节点外观;
- 能支持 html 事件;
缺点:
- 视口操作(画布拖拽,平移等)很难实现和维护;
- 对目前架构侵入较大,原本G6事件系统需要大量改造。
总结
曾经有人和我说过:“与其提供一个 60 分的替代方案,不如专心做一个 90 分的标准方案。”无论是以上哪种方式都无法完全满足我们想要的节点效果,因此G6不会在全局下支持 html 节点。
如果 html 节点是个强需求,可以在定义实例时指定用 SVG 渲染,利用 SVG 特有的 foreignObject 实现。
const graph = new G6.Graph({
renderer: 'svg',
...cfgs
});
SVG 版的 G 已支持此标签。定制节点时,按照如下方式:
G6.regiterNode('html', {
draw(cfg, group) {
const htmlShape = group.addShape('dom', {
attrs: {
html: '<div class="custom-node">your customized node</div>',
...attrs
}
});
return htmlShape;
}
});
note: 最好不要在 html 节点中嵌入表单元素。在用户输入信息时,偶尔会导致画布闪烁。