diff --git a/packages/g6/__tests__/bugs/element-node-icon-switch.spec.ts b/packages/g6/__tests__/bugs/element-node-icon-switch.spec.ts
new file mode 100644
index 00000000000..ec34b90c58d
--- /dev/null
+++ b/packages/g6/__tests__/bugs/element-node-icon-switch.spec.ts
@@ -0,0 +1,61 @@
+import { createGraph } from '@@/utils';
+
+describe('bug: element-node-icon-switch', () => {
+ it('change node icon', async () => {
+ const graph = createGraph({
+ animation: false,
+ data: {
+ nodes: [{ id: 'node-1', style: { x: 50, y: 50, iconText: 'Text' } }],
+ },
+ node: {
+ style: {},
+ },
+ });
+
+ await graph.draw();
+
+ await expect(graph).toMatchSnapshot(__filename, 'text-icon');
+
+ graph.updateNodeData([
+ {
+ id: 'node-1',
+ style: {
+ iconText: '',
+ iconSrc: 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*AzSISZeq81IAAAAAAAAAAAAADmJ7AQ/original',
+ },
+ },
+ ]);
+
+ await graph.draw();
+
+ await expect(graph).toMatchSnapshot(__filename, 'image-icon');
+
+ graph.updateNodeData([
+ {
+ id: 'node-1',
+ style: {
+ iconType: 'text',
+ iconText: 'Text',
+ iconSrc: 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*AzSISZeq81IAAAAAAAAAAAAADmJ7AQ/original',
+ },
+ },
+ ]);
+
+ await graph.draw();
+
+ await expect(graph).toMatchSnapshot(__filename, 'type-text');
+
+ graph.updateNodeData([
+ {
+ id: 'node-1',
+ style: {
+ iconType: 'image',
+ },
+ },
+ ]);
+
+ await graph.draw();
+
+ await expect(graph).toMatchSnapshot(__filename, 'type-image');
+ });
+});
diff --git a/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/image-icon.svg b/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/image-icon.svg
new file mode 100644
index 00000000000..216da1484fe
--- /dev/null
+++ b/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/image-icon.svg
@@ -0,0 +1,19 @@
+
\ No newline at end of file
diff --git a/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/text-icon.svg b/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/text-icon.svg
new file mode 100644
index 00000000000..c9f61b67034
--- /dev/null
+++ b/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/text-icon.svg
@@ -0,0 +1,21 @@
+
\ No newline at end of file
diff --git a/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/type-image.svg b/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/type-image.svg
new file mode 100644
index 00000000000..216da1484fe
--- /dev/null
+++ b/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/type-image.svg
@@ -0,0 +1,19 @@
+
\ No newline at end of file
diff --git a/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/type-text.svg b/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/type-text.svg
new file mode 100644
index 00000000000..7a11a1e322a
--- /dev/null
+++ b/packages/g6/__tests__/snapshots/bugs/element-node-icon-switch/type-text.svg
@@ -0,0 +1,21 @@
+
\ No newline at end of file
diff --git a/packages/g6/src/elements/shapes/base-shape.ts b/packages/g6/src/elements/shapes/base-shape.ts
index 0ce181b2db9..39012692300 100644
--- a/packages/g6/src/elements/shapes/base-shape.ts
+++ b/packages/g6/src/elements/shapes/base-shape.ts
@@ -66,7 +66,9 @@ export abstract class BaseShape extends
}
// create
- if (!target || target.destroyed) {
+ if (!target || target.destroyed || !(target instanceof Ctor)) {
+ target?.destroy();
+
const instance = new Ctor({ className, style });
container.appendChild(instance);
this.shapeMap[className] = instance;
diff --git a/packages/g6/src/elements/shapes/icon.ts b/packages/g6/src/elements/shapes/icon.ts
index cb70b682d4f..828df3dd40d 100644
--- a/packages/g6/src/elements/shapes/icon.ts
+++ b/packages/g6/src/elements/shapes/icon.ts
@@ -9,7 +9,18 @@ import { Image as GImage } from './image';
*
* Icon style
*/
-export interface IconStyleProps extends BaseShapeStyleProps, Partial, Omit {}
+export interface IconStyleProps extends BaseShapeStyleProps, Partial, Omit {
+ /**
+ * 手动指定节点类型
+ * - 'text' 文本
+ * - 'image' 图片
+ *
+ * Manually specify the node type
+ * - 'text' text
+ * - 'image' image
+ */
+ type: 'text' | 'image';
+}
/**
* 图标
@@ -25,14 +36,16 @@ export class Icon extends BaseShape {
super(options);
}
- private isGImage() {
- return !!this.getAttribute('src');
+ private isImage() {
+ const { type, src } = this.attributes;
+ if (type) return type === 'image';
+ return !!src;
}
protected getIconStyle(attributes: IconStyleProps = this.attributes): IconStyleProps {
const { width = 0, height = 0 } = attributes;
const style = this.getGraphicStyle(attributes);
- if (this.isGImage()) {
+ if (this.isImage()) {
return {
x: -width / 2,
y: -height / 2,
@@ -47,6 +60,6 @@ export class Icon extends BaseShape {
}
public render(attributes = this.attributes, container: Group = this): void {
- this.upsert('icon', (this.isGImage() ? GImage : GText) as any, this.getIconStyle(attributes), container);
+ this.upsert('icon', (this.isImage() ? GImage : GText) as any, this.getIconStyle(attributes), container);
}
}