diff --git a/packages/g6/__tests__/demo/static/common.ts b/packages/g6/__tests__/demo/static/common.ts
index 9c28e6cee46..785db143344 100644
--- a/packages/g6/__tests__/demo/static/common.ts
+++ b/packages/g6/__tests__/demo/static/common.ts
@@ -32,6 +32,7 @@ export * from './edge-quadratic';
export * from './graph-element';
export * from './layered-canvas';
export * from './node-circle';
+export * from './node-diamond';
export * from './node-ellipse';
export * from './node-image';
export * from './node-rect';
diff --git a/packages/g6/__tests__/demo/static/node-diamond.ts b/packages/g6/__tests__/demo/static/node-diamond.ts
new file mode 100644
index 00000000000..2a252347b0d
--- /dev/null
+++ b/packages/g6/__tests__/demo/static/node-diamond.ts
@@ -0,0 +1,62 @@
+import { Graph } from '@/src';
+import type { StaticTestCase } from '../types';
+
+export const nodeDiamond: StaticTestCase = async (context) => {
+ const { container, animation, theme } = context;
+ const data = {
+ nodes: [
+ { id: 'diamond' },
+ { id: 'diamond-halo' },
+ { id: 'diamond-badges' },
+ { id: 'diamond-ports' },
+ { id: 'diamond-active' },
+ { id: 'diamond-selected' },
+ { id: 'diamond-highlight' },
+ { id: 'diamond-inactive' },
+ { id: 'diamond-disabled' },
+ ],
+ };
+
+ const graph = new Graph({
+ container: container,
+ theme,
+ data,
+ node: {
+ style: {
+ type: 'diamond', // 👈🏻 Node shape type.
+ width: 40,
+ height: 40,
+ labelMaxWidth: 120,
+ labelText: (d: any) => d.id,
+ iconWidth: 20,
+ iconHeight: 20,
+ iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',
+ halo: (d: any) => d.id.includes('halo'),
+ ports: (d: any) =>
+ d.id.includes('ports')
+ ? [{ position: 'left' }, { position: 'right' }, { position: 'top' }, { position: 'bottom' }]
+ : [],
+ badges: (d: any) =>
+ d.id.includes('badges')
+ ? [
+ { text: 'A', position: 'right-top' },
+ { text: 'Important', position: 'right' },
+ { text: 'Notice', position: 'right-bottom' },
+ ]
+ : [],
+ badgeFontSize: 8,
+ badgePadding: [1, 4],
+ },
+ },
+ layout: {
+ type: 'grid',
+ },
+ animation,
+ });
+ await graph.render();
+ graph.setElementState('diamond-active', 'active');
+ graph.setElementState('diamond-selected', 'selected');
+ graph.setElementState('diamond-highlight', 'highlight');
+ graph.setElementState('diamond-inactive', 'inactive');
+ graph.setElementState('diamond-disabled', 'disabled');
+};
diff --git a/packages/g6/__tests__/integration/snapshots/static/node-diamond.svg b/packages/g6/__tests__/integration/snapshots/static/node-diamond.svg
new file mode 100644
index 00000000000..52642d2f820
--- /dev/null
+++ b/packages/g6/__tests__/integration/snapshots/static/node-diamond.svg
@@ -0,0 +1,813 @@
+
\ No newline at end of file
diff --git a/packages/g6/__tests__/unit/registry.spec.ts b/packages/g6/__tests__/unit/registry.spec.ts
index d9f4f08f771..d3fc0766400 100644
--- a/packages/g6/__tests__/unit/registry.spec.ts
+++ b/packages/g6/__tests__/unit/registry.spec.ts
@@ -4,6 +4,7 @@ import {
Cubic,
CubicHorizontal,
CubicVertical,
+ Diamond,
Ellipse,
Image,
Line,
@@ -26,6 +27,7 @@ describe('registry', () => {
rect: Rect,
star: Star,
triangle: Triangle,
+ diamond: Diamond,
});
expect(getExtensions('edge')).toEqual({
cubic: Cubic,
diff --git a/packages/g6/__tests__/unit/utils/point.spec.ts b/packages/g6/__tests__/unit/utils/point.spec.ts
index e8aa2d41484..7f691caa19c 100644
--- a/packages/g6/__tests__/unit/utils/point.spec.ts
+++ b/packages/g6/__tests__/unit/utils/point.spec.ts
@@ -2,6 +2,7 @@ import {
findNearestPoints,
getEllipseIntersectPoint,
getLinesIntersection,
+ getPolygonIntersectPoint,
getRectIntersectPoint,
isCollinear,
isHorizontal,
@@ -14,6 +15,7 @@ import {
toPointObject,
} from '@/src/utils/point';
import { Circle, Rect } from '@antv/g';
+import { getDiamondPoints } from '../../../src/utils/element';
describe('Point Functions', () => {
it('parsePoint', () => {
@@ -147,6 +149,24 @@ describe('Point Functions', () => {
expect(getEllipseIntersectPoint([100, 100], circle3.getBounds())).toEqual([120, 100]);
});
+ it('getDiamondIntersectPoint', () => {
+ expect(getPolygonIntersectPoint([100, 100], [0, 0], getDiamondPoints(100, 100))).toEqual([25, 25]);
+ expect(getDiamondPoints(0, 0)).toEqual([
+ [0, -0],
+ [0, 0],
+ [0, 0],
+ [-0, 0],
+ ]);
+ const height = 10;
+ const width = 10;
+ expect(getDiamondPoints(width, height)).toEqual([
+ [0, -height / 2],
+ [width / 2, 0],
+ [0, height / 2],
+ [-width / 2, 0],
+ ]);
+ });
+
it('findNearestPoints', () => {
expect(
findNearestPoints(
diff --git a/packages/g6/src/elements/index.ts b/packages/g6/src/elements/index.ts
index 802f1ae20f7..bde2e3dca15 100644
--- a/packages/g6/src/elements/index.ts
+++ b/packages/g6/src/elements/index.ts
@@ -1,3 +1,3 @@
export { CircleCombo } from './combos';
export { Cubic, CubicHorizontal, CubicVertical, Line, Polyline, Quadratic } from './edges';
-export { Circle, Ellipse, Image, Rect, Star, Triangle } from './nodes';
+export { Circle, Diamond, Ellipse, Image, Rect, Star, Triangle } from './nodes';
diff --git a/packages/g6/src/elements/nodes/diamond.ts b/packages/g6/src/elements/nodes/diamond.ts
new file mode 100644
index 00000000000..d6bc2a1ed94
--- /dev/null
+++ b/packages/g6/src/elements/nodes/diamond.ts
@@ -0,0 +1,42 @@
+import type { DisplayObjectConfig } from '@antv/g';
+import type { Point } from '../../types';
+import { getDiamondPoints } from '../../utils/element';
+import { getPolygonIntersectPoint } from '../../utils/point';
+import type { ParsedPolygonStyleProps, PolygonStyleProps } from './polygon';
+import { Polygon } from './polygon';
+
+type ExtendsStyleProps = {
+ width?: number;
+ height?: number;
+};
+export type DiamondStyleProps = PolygonStyleProps & ExtendsStyleProps;
+
+type ParsedDiamondStyleProps = ParsedPolygonStyleProps & Required;
+
+/**
+ * Draw diamond based on BaseNode, override drawKeyShape.
+ */
+export class Diamond extends Polygon {
+ constructor(options: DisplayObjectConfig) {
+ super(options);
+ }
+ private defaultWidth: number = 40;
+ private defaultHeight: number = 40;
+ private getWidth(attributes: ParsedDiamondStyleProps): number {
+ return attributes.width || this.defaultWidth;
+ }
+ private getHeight(attributes: ParsedDiamondStyleProps): number {
+ return attributes.height || this.defaultHeight;
+ }
+ protected getPoints(attributes: ParsedDiamondStyleProps): Point[] {
+ return getDiamondPoints(this.getWidth(attributes), this.getHeight(attributes));
+ }
+
+ public getIntersectPoint(point: Point): Point {
+ const { points } = this.getKeyStyle(this.attributes as ParsedDiamondStyleProps);
+ const center = [this.attributes.x, this.attributes.y] as Point;
+ return getPolygonIntersectPoint(point, center, points);
+ }
+
+ connectedCallback() {}
+}
diff --git a/packages/g6/src/elements/nodes/index.ts b/packages/g6/src/elements/nodes/index.ts
index c3a6e5c4f04..017ed1379e4 100644
--- a/packages/g6/src/elements/nodes/index.ts
+++ b/packages/g6/src/elements/nodes/index.ts
@@ -1,5 +1,6 @@
export { BaseNode } from './base-node';
export { Circle } from './circle';
+export { Diamond } from './diamond';
export { Ellipse } from './ellipse';
export { Image } from './image';
export { Rect } from './rect';
@@ -8,6 +9,7 @@ export { Triangle } from './triangle';
export type { BaseNodeStyleProps } from './base-node';
export type { CircleStyleProps } from './circle';
+export type { DiamondStyleProps } from './diamond';
export type { EllipseStyleProps } from './ellipse';
export type { ImageStyleProps } from './image';
export type { RectStyleProps } from './rect';
diff --git a/packages/g6/src/registry/build-in.ts b/packages/g6/src/registry/build-in.ts
index 59754aab000..2d86dbed913 100644
--- a/packages/g6/src/registry/build-in.ts
+++ b/packages/g6/src/registry/build-in.ts
@@ -6,6 +6,7 @@ import {
Cubic,
CubicHorizontal,
CubicVertical,
+ Diamond,
Ellipse,
Image,
Line,
@@ -86,6 +87,7 @@ export const BUILT_IN_EXTENSIONS: ExtensionRegistry = {
rect: Rect,
star: Star,
triangle: Triangle,
+ diamond: Diamond,
},
palette: {
spectral,
diff --git a/packages/g6/src/utils/element.ts b/packages/g6/src/utils/element.ts
index 4515afa01fe..e6a85a17bf5 100644
--- a/packages/g6/src/utils/element.ts
+++ b/packages/g6/src/utils/element.ts
@@ -377,6 +377,20 @@ export function getRectPoints(width: number, height: number): Point[] {
];
}
+/**
+ * Get Diamond PathArray.
+ * @param width - diamond width
+ * @param height - diamond height
+ * @returns The PathArray for G
+ */
+export function getDiamondPoints(width: number, height: number): Point[] {
+ return [
+ [0, -height / 2],
+ [width / 2, 0],
+ [0, height / 2],
+ [-width / 2, 0],
+ ];
+}
/**
* 元素是否可见
*
diff --git a/packages/site/examples/item/defaultNodes/demo/diamond.ts b/packages/site/examples/item/defaultNodes/demo/diamond.ts
new file mode 100644
index 00000000000..8e4abfbc51a
--- /dev/null
+++ b/packages/site/examples/item/defaultNodes/demo/diamond.ts
@@ -0,0 +1,56 @@
+import { Graph } from '@antv/g6';
+
+const data = {
+ nodes: [
+ { id: 'diamond' },
+ { id: 'diamond-halo' },
+ { id: 'diamond-badges' },
+ { id: 'diamond-ports' },
+ { id: 'diamond-active' },
+ { id: 'diamond-selected' },
+ { id: 'diamond-highlight' },
+ { id: 'diamond-inactive' },
+ { id: 'diamond-disabled' },
+ ],
+};
+
+const graph = new Graph({
+ container: 'container',
+ data,
+ node: {
+ style: {
+ type: 'diamond',
+ width: 40,
+ height: 40,
+ labelMaxWidth: 120,
+ labelText: (d: any) => d.id,
+ iconWidth: 20,
+ iconHeight: 20,
+ iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',
+ halo: (d: any) => d.id.includes('halo'),
+ ports: (d: any) =>
+ d.id.includes('ports')
+ ? [{ position: 'left' }, { position: 'right' }, { position: 'top' }, { position: 'bottom' }]
+ : [],
+ badges: (d: any) =>
+ d.id.includes('badges')
+ ? [
+ { text: 'A', position: 'right-top' },
+ { text: 'Important', position: 'right' },
+ { text: 'Notice', position: 'right-bottom' },
+ ]
+ : [],
+ badgeFontSize: 8,
+ badgePadding: [1, 4],
+ },
+ },
+ layout: {
+ type: 'grid',
+ },
+});
+await graph.render();
+graph.setElementState('diamond-active', 'active');
+graph.setElementState('diamond-selected', 'selected');
+graph.setElementState('diamond-highlight', 'highlight');
+graph.setElementState('diamond-inactive', 'inactive');
+graph.setElementState('diamond-disabled', 'disabled');