Registration and management system for custom node, edge, and combo shapes with built-in arrow and marker utilities. The shape system provides extensible rendering capabilities with lifecycle hooks, state management, and geometry calculations.
Register custom shapes for nodes, edges, and combos with the shape factory system.
/**
* Register custom node shape
* @param type - Shape type name
* @param shapeObj - Shape implementation object
*/
function registerNode(type: string, shapeObj: ShapeOptions): void;
/**
* Register custom edge shape
* @param type - Shape type name
* @param shapeObj - Shape implementation object
*/
function registerEdge(type: string, shapeObj: ShapeOptions): void;
/**
* Register custom combo shape
* @param type - Shape type name
* @param shapeObj - Shape implementation object
*/
function registerCombo(type: string, shapeObj: ShapeOptions): void;Usage Examples:
import { registerNode, registerEdge } from "@antv/g6-core";
// Register custom node shape
registerNode('custom-rect', {
draw(cfg, group) {
const rect = group.addShape('rect', {
attrs: {
x: -cfg.size[0] / 2,
y: -cfg.size[1] / 2,
width: cfg.size[0],
height: cfg.size[1],
fill: cfg.color || '#f0f0f0',
stroke: '#333'
}
});
return rect;
},
update(cfg, item) {
const keyShape = item.getKeyShape();
keyShape.attr({
width: cfg.size[0],
height: cfg.size[1],
fill: cfg.color
});
}
});
// Register custom edge shape
registerEdge('custom-line', {
draw(cfg, group) {
const line = group.addShape('path', {
attrs: {
path: this.getPath(cfg),
stroke: cfg.color || '#333',
lineWidth: cfg.lineWidth || 1
}
});
return line;
},
getPath(cfg) {
const startPoint = cfg.startPoint;
const endPoint = cfg.endPoint;
return [
['M', startPoint.x, startPoint.y],
['L', endPoint.x, endPoint.y]
];
}
});Complete interface for implementing custom shapes with all lifecycle methods and configuration options.
/**
* Shape implementation options interface
*/
interface ShapeOptions {
options?: ModelConfig;
type?: string;
itemType?: string;
shapeType?: string;
labelPosition?: string;
labelAutoRotate?: boolean;
jsx?: ShapeDefine;
// Core drawing methods
draw(cfg?: ModelConfig, group?: IGroup): IShape;
drawShape(cfg?: ModelConfig, group?: IGroup): IShape;
drawLabel(cfg: ModelConfig, group: IGroup): IShape;
// Configuration methods
getCustomConfig(cfg: ModelConfig): ModelConfig;
getLabelStyleByPosition(cfg: ModelConfig, labelCfg: ILabelConfig, group?: IGroup): LabelStyle;
getLabelStyle(cfg: ModelConfig, labelCfg: ILabelConfig, group: IGroup): LabelStyle;
// Lifecycle hooks
afterDraw(cfg?: ModelConfig, group?: IGroup, rst?: IShape): void;
afterUpdate(cfg?: ModelConfig, item?: Item): void;
// State management
setState(name?: string, value?: string | boolean, item?: Item): void;
// Geometry methods
getControlPoints(cfg: ModelConfig): IPoint[] | undefined;
getAnchorPoints(cfg?: ModelConfig): number[][] | undefined;
getSize(cfg: ModelConfig): number[];
getPathPoints(cfg: ModelConfig): ModelConfig;
// Update method
update(cfg: ModelConfig, item: Item): void;
// Text alignment helper
_getTextAlign(labelPosition: string, angle: number): string;
[key: string]: any;
}Factory system for managing and accessing registered shapes.
/**
* Base shape factory for managing shape types
*/
interface ShapeFactoryBase {
defaultShapeType: string;
className: string | null;
/**
* Get shape implementation by type
* @param type - Shape type name
* @returns Shape implementation object
*/
getShape(type?: string): ShapeOptions;
/**
* Draw shape with specified type and configuration
* @param type - Shape type name
* @param cfg - Model configuration
* @param group - Graphics group
* @returns Created shape element
*/
draw(type: string, cfg: ModelConfig, group: IGroup): IShape;
/**
* Update shape with new configuration
* @param type - Shape type name
* @param cfg - Updated configuration
* @param item - Item instance
*/
baseUpdate(type: string, cfg: ModelConfig, item: Item): void;
/**
* Set shape state
* @param type - Shape type name
* @param name - State name
* @param value - State value
* @param item - Item instance
*/
setState(type: string, name: string, value: string | boolean, item: Item): void;
/**
* Check if shape should be updated
* @param type - Shape type name
* @returns True if should update
*/
shouldUpdate(type: string): boolean;
/**
* Get control points for edge
* @param type - Shape type name
* @param cfg - Model configuration
* @returns Array of control points
*/
getControlPoints(type: string, cfg: ModelConfig): IPoint[] | undefined;
/**
* Get anchor points for connections
* @param type - Shape type name
* @param cfg - Model configuration
* @returns Array of anchor points
*/
getAnchorPoints(type: string, cfg: ModelConfig): number[][] | undefined;
}Built-in arrow shape generators for edge endpoints.
/**
* Arrow shape utilities for edge endpoints
*/
declare const Arrow: {
/**
* Generate triangle arrow path
* @param width - Arrow width
* @param length - Arrow length
* @param d - Distance from edge end
* @returns SVG path string
*/
triangle(width?: number, length?: number, d?: number): string;
/**
* Generate vee-shaped arrow path
* @param width - Arrow width
* @param length - Arrow length
* @param d - Distance from edge end
* @returns SVG path string
*/
vee(width?: number, length?: number, d?: number): string;
/**
* Generate circular arrow path
* @param r - Circle radius
* @param d - Distance from edge end
* @returns SVG path string
*/
circle(r?: number, d?: number): string;
/**
* Generate rectangular arrow path
* @param width - Rectangle width
* @param length - Rectangle length
* @param d - Distance from edge end
* @returns SVG path string
*/
rect(width?: number, length?: number, d?: number): string;
/**
* Generate diamond arrow path
* @param width - Diamond width
* @param length - Diamond length
* @param d - Distance from edge end
* @returns SVG path string
*/
diamond(width?: number, length?: number, d?: number): string;
/**
* Generate combined triangle and rectangle arrow path
* @param tWidth - Triangle width
* @param tLength - Triangle length
* @param rWidth - Rectangle width
* @param rLength - Rectangle length
* @param gap - Gap between shapes
* @param d - Distance from edge end
* @returns SVG path string
*/
triangleRect(tWidth?: number, tLength?: number, rWidth?: number, rLength?: number, gap?: number, d?: number): string;
};Usage Examples:
import { Arrow } from "@antv/g6-core";
// Use in edge configuration
const edgeConfig = {
startArrow: {
path: Arrow.triangle(10, 15),
fill: '#333'
},
endArrow: {
path: Arrow.vee(8, 12),
fill: '#666'
}
};
// Custom arrow configurations
const customTriangle = Arrow.triangle(12, 18, 2);
const customCircle = Arrow.circle(5, 1);
const customDiamond = Arrow.diamond(10, 10, 0);Built-in marker shape generators for collapse/expand controls and indicators.
/**
* Marker shape utilities for UI controls
*/
declare const Marker: {
/**
* Generate collapse marker points (minus sign)
* @param x - Center X coordinate
* @param y - Center Y coordinate
* @param r - Marker radius
* @returns Array of point coordinates
*/
collapse(x: number, y: number, r: number): number[][];
/**
* Generate expand marker points (plus sign)
* @param x - Center X coordinate
* @param y - Center Y coordinate
* @param r - Marker radius
* @returns Array of point coordinates
*/
expand(x: number, y: number, r: number): number[][];
/**
* Generate upward triangle marker points
* @param x - Center X coordinate
* @param y - Center Y coordinate
* @param r - Marker radius
* @returns Array of point coordinates
*/
upTriangle(x: number, y: number, r: number): number[][];
/**
* Generate downward triangle marker points
* @param x - Center X coordinate
* @param y - Center Y coordinate
* @param r - Marker radius
* @returns Array of point coordinates
*/
downTriangle(x: number, y: number, r: number): number[][];
};Usage Examples:
import { Marker } from "@antv/g6-core";
// Create collapse/expand controls
const collapsePoints = Marker.collapse(50, 50, 8);
const expandPoints = Marker.expand(50, 50, 8);
// Create directional indicators
const upArrow = Marker.upTriangle(100, 100, 6);
const downArrow = Marker.downTriangle(100, 120, 6);
// Use in shape drawing
registerNode('collapsible-node', {
draw(cfg, group) {
// Draw main shape
const rect = group.addShape('rect', {
attrs: { /* rect attributes */ }
});
// Add collapse/expand marker
const isCollapsed = cfg.collapsed;
const markerPoints = isCollapsed ?
Marker.expand(cfg.x + 20, cfg.y - 10, 4) :
Marker.collapse(cfg.x + 20, cfg.y - 10, 4);
group.addShape('polyline', {
attrs: {
points: markerPoints,
stroke: '#666',
lineWidth: 2
}
});
return rect;
}
});Configure label positioning and styling for shapes.
/**
* Label configuration interface
*/
interface ILabelConfig {
position?: string;
offset?: number;
refX?: number;
refY?: number;
autoRotate?: boolean;
style?: LabelStyle;
}
/**
* Shape definition type
*/
type ShapeDefine = string | ((cfg: ModelConfig) => string);Example of a complete custom shape implementation with all features:
// Complete custom node shape example
registerNode('advanced-node', {
// Shape configuration
options: {
size: [100, 60],
labelCfg: {
position: 'center',
style: {
fill: '#333'
}
}
},
// Main drawing method
draw(cfg, group) {
const size = this.getSize(cfg);
const color = cfg.color || '#f0f0f0';
// Draw main shape
const rect = group.addShape('rect', {
attrs: {
x: -size[0] / 2,
y: -size[1] / 2,
width: size[0],
height: size[1],
fill: color,
stroke: '#333',
radius: 4
},
name: 'main-rect'
});
// Draw label if exists
if (cfg.label) {
this.drawLabel(cfg, group);
}
return rect;
},
// Update method
update(cfg, item) {
const keyShape = item.getKeyShape();
const size = this.getSize(cfg);
keyShape.attr({
width: size[0],
height: size[1],
fill: cfg.color || '#f0f0f0'
});
},
// State management
setState(name, value, item) {
const keyShape = item.getKeyShape();
if (name === 'hover') {
keyShape.attr({
fill: value ? '#e6f7ff' : item.getModel().color || '#f0f0f0'
});
} else if (name === 'selected') {
keyShape.attr({
stroke: value ? '#1890ff' : '#333',
lineWidth: value ? 2 : 1
});
}
},
// Anchor points for connections
getAnchorPoints() {
return [
[0, 0.5], // left
[1, 0.5], // right
[0.5, 0], // top
[0.5, 1] // bottom
];
},
// Size calculation
getSize(cfg) {
let size = cfg.size || this.options.size;
if (typeof size === 'number') {
size = [size, size];
}
return size;
},
// After draw hook
afterDraw(cfg, group, shape) {
// Add any post-drawing effects
if (cfg.badge) {
group.addShape('circle', {
attrs: {
x: 30,
y: -20,
r: 6,
fill: '#f04134'
},
name: 'badge'
});
}
}
});interface ModelConfig {
type?: string;
label?: string | LabelStyle;
labelCfg?: ILabelConfig;
x?: number;
y?: number;
size?: number | number[];
color?: string;
anchorPoints?: number[][];
visible?: boolean;
[key: string]: any;
}
interface LabelStyle {
fill?: string;
fontSize?: number;
fontWeight?: string | number;
textAlign?: string;
textBaseline?: string;
fontFamily?: string;
[key: string]: any;
}
interface IShape {
attr(name: string, value?: any): any;
attr(attrs: object): void;
remove(): void;
show(): void;
hide(): void;
[key: string]: any;
}
interface IGroup {
addShape(type: string, config: { attrs: object; name?: string }): IShape;
getChildren(): IShape[];
clear(): void;
[key: string]: any;
}
interface IShapeBase extends IShape {
// Extended shape interface
}
type ITEM_TYPE = 'node' | 'edge' | 'combo';
interface ArrowConfig {
path?: string;
fill?: string;
stroke?: string;
lineWidth?: number;
[key: string]: any;
}