The issue has been closed

posted by Aarebecca 8 months ago 
constructor(options: RouterNodeStyleProps) {
console.log('1. svg node constructor...');
super(options);
console.log('2. svg node constructor...');
// 自定义节点的配置,实际是通过options传入的
this.getType = (data: NodeData) => SvgNodeType;
}
第我期望写一个自定义节点,继承自BaseNode
它能够根据业务数据,绘制不同的svg图标。如constructor
,我提供了一个getType
方法用来根据业务数据获取节点类型
protected drawKeyShape(attributes: Required<RouterNodeStyleProps>, shapeGroup: Group) {
const graph = attributes.context.graph;
const nodeId = shapeGroup.id;
const nodeData = graph.getNodeData(nodeId);
// 这里提前访问了constructor中未完成定义的变量,报错
const svgNodeType = this.getType(nodeData);
const svgPath = this.nodeMap[svgNodeType];
return undefined;
}
然后在绘制图形(调用drawKeyShape
)时,调用this.getType
,并传入当前节点的原始业务数据,绘制对应的节点图形。
但现在的状况是,由于自定义节点中的函数调用,会在调用super
方法后,执行this.getType
赋值之前,调用drawKeyShape
函数,此时会在drawKeyShape
中调用一个未定义的this.getType
属性报错。
posted by zmbxy 8 months ago
@zmbxy 为什么要在构造函数中赋值 this.getType
,直接定义为成员方法不就行了吗
posted by Aarebecca 8 months ago
我现在有两张不同业务的图,它们的节点图形不同,数据不同,我希望我的自定义节点能够在外部动态配置svg节点或者后续的替换也好,把svg节点绘制这块统一一下,外部自行根据节点数据,绘制不同的图形,如果不能动态配置,那我只能在drawKeyShape
中通过写代码逻辑控制,但这样一来,实现就很麻烦了,需要写很多硬编码在里面了。
posted by zmbxy 8 months ago
@Aarebecca 我参考G6实现,写了一段简短的代码来复现这个问题,和我前面提到的那个问题是相同的结果
interface BaseShapeOptions {
a: number;
b: string;
}
abstract class BaseShape {
options: BaseShapeOptions;
constructor(options: BaseShapeOptions) {
this.options = options;
this.render();
console.log('this is is CustomNode: ', this instanceof CustomNode);
}
public abstract render(): void;
}
abstract class BaseNode extends BaseShape {
constructor(options: BaseShapeOptions) {
super(options);
}
public abstract drawKeyShape(): void;
render(): void {
this.drawKeyShape();
}
}
class CustomNode extends BaseNode {
c: number;
constructor(options: BaseShapeOptions) {
console.log('========== 1.开始实例化自定义节点 ==========');
super(options);
console.log('========== 2.初始化自定义节点独有的属性 ==========');
this.c = 10;
console.log('========== 3.自定义节点实例化完成 ==========');
}
drawKeyShape(): void {
console.log('========== 4.调用绘制图形方法,绘制图形 ==========')
}
}
new CustomNode({ a: 1, b: '2' });
以上代码的打印结果如下:
========== 1.开始实例化自定义节点 ==========
========== 4.调用绘制图形方法,绘制图形 ==========
base shape this: true
========== 2.初始化自定义节点独有的属性 ==========
========== 3.自定义节点实例化完成 ==========
出现问题的点在于abstract class BaseShape
,在实例化时就调用了render
函数导致的,使用面向对象编程,我们是为了易扩展、易维护,而现在这种状况,除了能重写一下drawKeyShape
,其它的好像也扩展不了什么,就丢失了它的意义了。
而且从另一个角度来说,我的自定义节点未实例化完成,就去调用它的方法,这种感觉就像是我定义了一个关于汽车的要点要素,然后我去按照这个框架,自己造一辆车,但是我车没造好,就要它能跑起来,这显然是不合理的。
这只是我自己的一些想法,建议团队可以考虑一下。
posted by zmbxy 8 months ago
@Aarebecca 哈喽,这个问题我看好几天没有回复了,这个还有在跟踪吗?
我们目前还在用4.x版本,现在也在了解,熟悉v5版本新API,为v4版本迁移做准备,如果团队不认为这是个问题或者设计就是如此,那我就想其它方法来封装了。
posted by zmbxy 8 months ago
@zmbxy G6 5.0 的元素基类会在构造方法中调用 render
以执行各部分图形的绘制流程。当要进行元素自定义时,通常有以下两种途径:
直接覆写基类的绘制方法,例如覆写 drawKeyShape
将主图形绘制为其他图形
可以参考内置节点的实现,该情况下需要遵从基类元素的绘制流程
class Circle extends BaseNode {
drawKeyShape(attributes, container) {
// draw key shape here
}
}
新增自定义绘制方法,例如新增 drawCustomShape
方法,并在 render 中调用该方法
使用该方式你可以在不影响 render
逻辑的情况下任意定制你的绘制流程
// 在圆形节点的基础上额外绘制自定义元素
class CustomNode extends Circle {
render(attributes, container) {
super.render(attributes, container);
this.drawCustomShape(attributes, container);
}
drawCustomShape(attributes, container) {
// draw custom shape here
}
}
"abstract class BaseShape,在实例化时就调用了render函数"
至于你提到的问题,如果你想充分的定制绘制逻辑,可以覆写 render 方法,并不要调用 super.render,然后完全重新编写绘制逻辑即可
posted by Aarebecca 8 months ago
@Aarebecca
<img width="1228" alt="image" src="https://github.com/user-attachments/assets/bb603cc4-9e36-43b6-850b-5f1bb825f693">
那请问一下,如果要自定义属性,有办法么?
posted by zmbxy 8 months ago
@zmbxy
自定义属性的传入:
Graph Options
const graph = new Graph({
node: {
style: {
customStyle: d => d.data.xxx // 使用数据属性作为自定义属性
},
},
});
消费自定义属性:
class CustomNode extends Circle {
render(attributes, container) {
super.render(attributes, container);
this.drawCustomShape(attributes, container);
}
drawCustomShape(attributes, container) {
// get custom style from attributes
const { customStyle } = attributes;
}
}
posted by Aarebecca 8 months ago
posted by zmbxy 8 months ago