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 @@ + + + + + + + + + + + + + + + + + + diamond + + + + + + + + + + + + + + + + + + + + + + + diamond-halo + + + + + + + + + + + + + + + + + + + + diamond-badges + + + + + + + + + + + + + + + + A + + + + + + + + + + + + Important + + + + + + + + + + + + Notice + + + + + + + + + + + + + + + + diamond-ports + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diamond-active + + + + + + + + + + + + + + + + + + + + + + + diamond-select... + + + + + + + + + + + + + + + + + + + + diamond-highlight + + + + + + + + + + + + + + + + + + + + diamond-inactive + + + + + + + + + + + + + + + + + + + + diamond-disabled + + + + + + + + + + + + + \ 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');