feat: add necessary types (#4182)

* feat: add necessary types

* feat: add combo data type

* feat: add animate attribute type to graph elements

* chore: format notes
This commit is contained in:
Yanyan Wang 2023-01-04 20:37:40 +08:00 committed by Yanyan-Wang
parent 3095544cdf
commit d4b91357e6
14 changed files with 654 additions and 5 deletions

View File

@ -58,6 +58,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"@antv/g": "^5.15.7"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^25.2.1", "@types/jest": "^25.2.1",
@ -82,4 +83,4 @@
"typescript": "^4.6.3", "typescript": "^4.6.3",
"stats-js": "^1.0.1" "stats-js": "^1.0.1"
} }
} }

View File

@ -1,4 +0,0 @@
export * from './graph';
export * from './behavior';
export * from './item';
export * from './shape';

View File

@ -0,0 +1,50 @@
export interface AnimateCfg {
/**
* Whether enable animation.
* @type {boolean}
*/
enable: boolean;
/**
* Duration of one animation.
* @type {number}
*/
duration?: number;
/**
* Easing function.
* @type {string}
*/
easing?: string;
/**
* Delay of the animation.
* @type {function}
*/
delay?: number;
/**
* Whether repeat.
* @type {boolean}
*/
repeat?: boolean;
/**
* Called after the animation is finished.
* @type {function}
*/
callback?: () => void;
/**
* Called after the animation is paused.
* @type {function}}
*/
pauseCallback?: () => void;
/**
* Called after the animation is resumed.
* @type {function}
*/
resumeCallback?: () => void;
};
export type AnimateWhen = 'show' | 'exit' | 'update' | 'last';
export interface AnimateAttr {
when: AnimateWhen;
type: string;
[param: string]: unknown;
}

View File

@ -0,0 +1,64 @@
import { AnimateAttr } from "./animate";
import { Padding } from "./common";
import { Encode, LabelBackground, ShapeAttrEncode, ShapesEncode } from "./item";
import { AnchorPoint } from "./node";
export type ComboLabelPosition = 'bottom' | 'top' | 'left' | 'left-top' | 'right' | 'ouside-top' | 'outside-left' | 'outside-right' | 'outside-bottom';
/** User input data. */
export interface ComboUserData {
id: string;
parentId?: string;
}
/** Inner combo data, clone and transform from user data. */
export interface ComboModel extends ComboUserData {
visible?: boolean;
label?: string;
}
/** Displayed data, only for drawing and not received by users. */
export interface ComboDisplayModel extends ComboModel {
keyShape?: {
[shapeAttr: string]: unknown;
animate: AnimateAttr;
};
labelShape?: {
position?: ComboLabelPosition;
offsetX?: number;
offsetY?: number;
background?: LabelBackground;
[shapeAttr: string]: unknown;
animate: AnimateAttr;
};
iconShape?: {
[shapeAttr: string]: unknown;
animate: AnimateAttr;
};
otherShapes?: {
[shapeName: string]: {
[shapeAttr: string]: unknown;
animate: AnimateAttr;
}
};
anchorPoints?: AnchorPoint[];
fixSize?: number | number[];
padding?: Padding;
}
interface ComboLabelShapeAttrEncode extends ShapeAttrEncode { // TODO: extends Text shape attr, import from G
position?: ComboLabelPosition | Encode<ComboLabelPosition>;
offsetX?: number | Encode<number>;
offsetY?: number | Encode<number>;
background?: LabelBackground | Encode<LabelBackground>;
}
export interface ComboShapesEncode extends ShapesEncode {
labelShape?: ComboLabelShapeAttrEncode;
anchorPoints?: AnchorPoint[] | Encode<AnchorPoint[]>;
fixSize?: number | number[] | Encode<number | number[]>;
padding?: Padding | Encode<Padding>;
}
export interface ComboEncode extends ComboShapesEncode {
type?: string | Encode<string>;
}

View File

@ -0,0 +1,6 @@
export type Padding = number | number[];
export type Point = {
x: number;
y: number
}

View File

@ -0,0 +1,20 @@
import { EdgeUserData } from "./edge";
import { NodeUserData } from "./node"
export interface GraphData {
nodes?: NodeUserData[];
edges?: EdgeUserData[];
combos?: NodeUserData[]; // TODO: combo data's interface
}
export interface InlineDataConfig {
type: 'inline';
value: GraphData;
}
export interface FetchDataConfig {
type: 'fetch';
value: string;
}
export type TransformerFn = (data: GraphData) => GraphData

View File

@ -0,0 +1,64 @@
import { AnimateAttr } from "./animate";
import { Encode, LabelBackground, ShapeAttrEncode, ShapesEncode } from "./item";
/** User input data. */
export interface EdgeUserData {
id: string,
source: string,
target: string,
}
/** Inner node data, clone and transform from user data. */
export interface EdgeModel extends EdgeUserData {
visible?: boolean;
label?: string;
}
/** Displayed data, only for drawing and not received by users. */
export interface EdgeDisplayModel extends EdgeModel {
keyShape?: {
[shapeAttr: string]: unknown;
animate: AnimateAttr;
};
labelShape?: {
position?: EdgeLabelPosition;
offsetX?: number;
offsetY?: number;
background?: LabelBackground;
autoRotate?: boolean;
[shapeAttr: string]: unknown;
animate: AnimateAttr;
};
iconShape?: {
[shapeAttr: string]: unknown;
animate: AnimateAttr;
};
otherShapes?: {
[shapeName: string]: {
[shapeAttr: string]: unknown;
animate: AnimateAttr;
}
};
sourceAnchor?: number;
targetAnchor?: number;
}
export type EdgeLabelPosition = 'start' | 'middle' | 'end';
interface EdgeLabelShapeAttrEncode extends ShapeAttrEncode {
position?: EdgeLabelPosition | Encode<EdgeLabelPosition>;
offsetX: number | Encode<number>;
offsetY?: number | Encode<number>;
background?: LabelBackground | Encode<LabelBackground>;
autoRotate?: boolean | Encode<boolean>;
}
export interface EdgeShapesEncode extends ShapesEncode {
labelShape?: EdgeLabelShapeAttrEncode;
sourceAnchor?: number;
targetAnchor?: number;
}
export interface EdgeEncode extends EdgeShapesEncode {
type?: string | Encode<string>;
}

View File

@ -0,0 +1,262 @@
import EventEmitter from '@antv/event-emitter';
import { AnimateCfg } from './animate';
import { ComboUserData } from './combo';
import { Padding, Point } from './common';
import { GraphData } from './data';
import { EdgeUserData } from './edge';
import { ITEM_TYPE } from './item';
import { LayoutCommonConfig } from './layout';
import { NodeUserData } from './node';
import { Specification } from './spec';
import { FitViewRules, GraphAlignment } from './view';
// TODO: 1. BehaviorCfg type; 2. Item type;
export interface IGraph extends EventEmitter {
/**
* Update the specs(configurations).
*/
updateSpec: (spec: Specification) => void;
/**
* Input data and render the graph.
* @param data
* @returns
*/
read: (data: GraphData) => void;
/**
* Clear the graph, means remove all the items on the graph.
* @returns
*/
clear: () => void;
// ===== view operations =====
/**
* Move the graph with a relative vector.
* @param dx x of the relative vector
* @param dy y of the relative vector
* @param animateCfg animation configurations
* @returns
* @group View
*/
move: (dx: number, dy: number, animateCfg?: AnimateCfg) => void;
/**
* Move the graph and align to a point.
* @param x position on the canvas to align
* @param y position on the canvas to align
* @param alignment alignment of the graph content
* @param animateCfg animation configurations
* @returns
* @group View
*/
moveTo: (x: number, y: number, alignment: GraphAlignment, animateCfg?: AnimateCfg) => void;
/**
* Zoom the graph with a relative ratio.
* @param ratio relative ratio to zoom
* @param center zoom center
* @param animateCfg animation configurations
* @returns
* @group View
*/
zoom: (ratio: number, center?: Point, animateCfg?: AnimateCfg) => void;
/**
* Zoom the graph to a specified ratio.
* @param toRatio specified ratio
* @param center zoom center
* @param animateCfg animation configurations
* @returns
* @group View
*/
zoomTo: (toRatio: number, center?: Point, animateCfg?: AnimateCfg) => void;
/**
* Fit the graph content to the view.
* @param padding padding while fitting
* @param rules rules for fitting
* @param animateCfg animation configurations
* @returns
* @group View
*/
fitView: (padding?: Padding, rules?: FitViewRules, animateCfg?: AnimateCfg) => void;
/**
* Fit the graph center to the view center.
* @param animateCfg animation configurations
* @returns
* @group View
*/
fitCenter: (animateCfg?: AnimateCfg) => void;
/**
* Move the graph to make the item align the view center.
* @param item node/edge/combo item or its id
* @param animateCfg animation configurations
* @returns
* @group View
*/
focusItem: (item: Item | string, animateCfg?: AnimateCfg) => void;
/**
* Move (and zoom) the graph to make the items align (and fit) the view center.
* @param items node/edge/combo item array or their id array
* @param animateCfg animation configurations
* @returns
* @group View
*/
focusItems: (items: Item[] | string[], zoomToFit?: boolean, animateCfg?: AnimateCfg) => void;
// ===== item operations =====
/**
* Find an element item according to id.
* @param id
* @returns
* @group Item
*/
findById: <T extends Item>(id: string) => T | undefined;
/**
* Find items which has the state.
* @param itemType item type
* @param state state name
* @param additionalFilter additional filter function
* @returns items that is the type and has the state
* @group Item
*/
findByState: <T extends Item>(itemType: ITEM_TYPE, state: string, additionalFilter?: (item: Item) => boolean) => T[];
/**
* Add an item to the graph.
* @param itemType item type
* @param model user data
* @param stack whether push this operation to stack
* @returns the added item
* @group Item
*/
addItem: (itemType: ITEM_TYPE, model: NodeUserData | EdgeUserData | ComboUserData, stack?: boolean) => Item;
/**
* Add items to the graph.
* @param itemType item type
* @param models user datas
* @param stack whether push this operation to stack
* @returns the added items
* @group Item
*/
addItems: (itemType: ITEM_TYPE, models: NodeUserData[] | EdgeUserData[] | ComboUserData[], stack?: boolean) => Item[];
/**
* Remove an item from the graph.
* @param item the item to be removed
* @param stack whether push this operation to stack
* @returns
* @group Item
*/
removeItem: (item: Item | string, stack?: boolean) => void;
/**
* Remove multiple items from the graph.
* @param items the items to be removed
* @param stack whether push this operation to stack
* @returns
* @group Item
*/
removeItems: (items: (Item | string)[], stack?: boolean) => void;
/**
* Update an item on the graph.
* @param {Item} item item or id
* @param {EdgeConfig | NodeConfig} cfg incremental updated configs
* @param {boolean} stack true
* @group Item
*/
updateItem: (item: Item | string, cfg: Partial<NodeUserData> | Partial<EdgeUserData> | Partial<ComboUserData>, stack?: boolean) => Item;
/**
* Show the item.
* @param item the item to be shown
* @returns
* @group Item
*/
showItem: (item: Item | string) => void;
/**
* Hide the item.
* @param item the item to be hidden
* @returns
* @group Item
*/
hideItem: (item: Item | string) => void;
/**
* Set state for the item.
* @param item the item to be set
* @param state the state name
* @param value state value
* @returns
* @group Item
*/
setItemState: (item: Item | string, state: string, value: boolean) => void;
// ===== combo operations =====
/**
* Create a new combo with existing child nodes and combos.
* @param combo combo ID or Combo model
* @param childrenIds id array of children of the new combo
* @group Combo
*/
createCombo: (combo: string | ComboUserData, childrenIds: string[], stack?: boolean) => void;
/**
* dissolve combo
* @param {String | ICombo} item combo item or id to be dissolve
*/
uncombo: (item: string | ICombo, stack?: boolean) => void;
/**
* Collapse a combo.
* @param comboId combo id or item
* @group Combo
*/
collapseCombo: (combo: string | ICombo, stack?: boolean) => void;
/**
* Expand a combo.
* @group Combo
* @param combo combo ID combo
* @group Combo
*/
expandCombo: (combo: string | ICombo, stack?: boolean) => void;
// ===== layout =====
/**
* Layout the graph (with current configurations if cfg is not assigned).
* @param {LayoutCommonConfig} cfg layout configurations. if assigned, the layout spec of the graph will be updated in the same time
* @param {GraphAlignment} align align the result
* @param {Point} canvasPoint align the result
* @param {boolean} stack push it into stack
* @group Layout
*/
layout: (cfg?: LayoutCommonConfig, align?: GraphAlignment, canvasPoint?: Point, stack?: boolean) => void;
// ===== interaction =====
/**
* Switch mode.
* @param mode mode name
* @returns
* @group Interaction
*/
setMode: (mode: string) => void;
/**
* Add behavior(s) to mode(s).
* @param behaviors behavior names or configs
* @param modes mode names
* @returns
*/
addBehaviors: (behaviors: BehaviorName | BehaviorCfg | BehaviorName[] | BehaviorCfg[], modes: string | string[]) => void;
/**
* Remove behavior(s) from mode(s).
* @param behaviors behavior names or configs
* @param modes mode names
* @returns
* @group Interaction
*/
removeBehaviors: (behaviors: BehaviorName | BehaviorCfg | BehaviorName[] | BehaviorCfg[], modes: string | string[]) => void;
/**
* Update behavior(s) on a mode.
* @param behavior behavior configs, whose name indicates the behavior to be updated
* @param mode mode name
* @returns
* @group Interaction
*/
updateBehavior: (behavior: BehaviorCfg, mode?: string) => void;
}

View File

@ -0,0 +1,5 @@
export { IGraph } from './graph';
export { GraphData } from './data';
export { NodeUserData, NodeModel, NodeDisplayModel } from './node';
export { EdgeUserData, EdgeModel, EdgeDisplayModel } from './edge';
export { ComboUserData, ComboModel, ComboDisplayModel } from './combo';

View File

@ -0,0 +1,32 @@
import { AnimateAttr } from "./animate";
export interface Encode<T> {
fields: string[],
formatter: (values: unknown[]) => T;
}
export interface ShapeAttrEncode {
[shapeAttr: string]: unknown | Encode<unknown>;
animate: AnimateAttr | Encode<AnimateAttr>;
};
export interface LabelBackground {
fill?: string;
stroke?: string;
lineWidth?: number;
radius?: number[] | number;
padding?: number[] | number;
};
export interface ShapesEncode {
keyShape?: ShapeAttrEncode;
iconShape?: ShapeAttrEncode;
otherShapes?: {
[shapeName: string]: {
[shapeAtrr: string]: unknown | Encode<unknown>;
animate: AnimateAttr | Encode<AnimateAttr>;
}
};
}
export type ITEM_TYPE = 'node' | 'edge' | 'combo';

View File

@ -0,0 +1,9 @@
export interface LayoutCommonConfig {
type?: string;
gpuEnabled?: boolean;
workerEnabled?: boolean;
// Works when workerEnabled is true, config it with a visitable url to avoid visiting online version.
workerScriptURL?: string;
}

View File

@ -0,0 +1,65 @@
import { AnimateAttr } from "./animate";
import { Encode, LabelBackground, ShapeAttrEncode, ShapesEncode } from "./item";
export type NodeLabelPosition = 'bottom' | 'center' | 'top' | 'left' | 'right';
/** User input data. */
export interface NodeUserData {
id: string;
parentId?: string;
}
/** Inner node data, clone and transform from user data. */
export interface NodeModel extends NodeUserData {
visible?: boolean;
label?: string;
}
/** Displayed data, only for drawing and not received by users. */
export interface NodeDisplayModel extends NodeModel {
keyShape?: {
[shapeAttr: string]: unknown;
animate: AnimateAttr;
};
labelShape?: {
position?: NodeLabelPosition;
offsetX?: number;
offsetY?: number;
background?: LabelBackground;
[shapeAttr: string]: unknown;
animate: AnimateAttr;
};
iconShape?: {
[shapeAttr: string]: unknown;
animate: AnimateAttr;
};
otherShapes?: {
[shapeName: string]: {
[shapeAttr: string]: unknown;
animate: AnimateAttr;
}
};
anchorPoints?: AnchorPoint[]
}
/** Anchor points, for linking edges and drawing circles. */
export interface AnchorPoint {
position?: [number, number]; // range from 0 to 1
show?: boolean;
[shapeAttr: string]: unknown;
animate: AnimateAttr;
}
interface NodeLabelShapeAttrEncode extends ShapeAttrEncode { // TODO: extends Text shape attr, import from G
position?: NodeLabelPosition | Encode<NodeLabelPosition>;
offsetX?: number | Encode<number>;
offsetY?: number | Encode<number>;
background?: LabelBackground | Encode<LabelBackground>;
}
export interface NodeShapesEncode extends ShapesEncode {
labelShape?: NodeLabelShapeAttrEncode;
anchorPoints?: AnchorPoint[] | Encode<AnchorPoint[]>
}
export interface NodeEncode extends NodeShapesEncode {
type?: string | Encode<string>;
}

View File

@ -0,0 +1,68 @@
import { AnimateCfg } from "./animate";
import { Point } from "./common";
import { FetchDataConfig, InlineDataConfig, TransformerFn } from "./data";
import { EdgeDisplayModel, EdgeEncode, EdgeModel, EdgeShapesEncode } from "./edge";
import { NodeDisplayModel, NodeEncode, NodeModel, NodeShapesEncode } from "./node";
import { GraphAlignment } from "./view";
import { LayoutCommonConfig } from "./layout";
type rendererName = 'canvas' | 'svg' | 'webgl';
export interface Specification {
type: 'graph' | 'tree';
width?: number;
height?: number;
renderer?: rendererName | {
type: rendererName,
pixelRatio: number,
headless: boolean,
};
zoom?: number;
autoFit?: 'view' | 'center' | {
position: Point,
alignment: GraphAlignment
};
optimizeThreshold?: number;
/** data */
data: InlineDataConfig | FetchDataConfig; // TODO: more
transform?: string[] | {
type: string,
[param: string]: unknown // TODO: generate by plugins
}[] | TransformerFn[];
/** item */
node?: (data: NodeModel) => NodeDisplayModel | NodeEncode;
edge?: (data: EdgeModel) => EdgeDisplayModel | EdgeEncode;
combo?: (data: NodeModel) => NodeDisplayModel | NodeEncode; // TODO: combo's type
/** item state styles */
nodeState?: {
[state: string]: (data: NodeModel) => NodeDisplayModel | NodeShapesEncode;
};
edgeState?: {
[state: string]: (data: EdgeModel) => EdgeDisplayModel | EdgeShapesEncode;
};
comboState?: {
[state: string]: (data: NodeModel) => NodeDisplayModel | NodeShapesEncode;
};
/** layout */
layout?: LayoutCommonConfig | LayoutCommonConfig[]; // TODO: Config comes from @antv/layout
/** interaction */
modes?: {
default: BehaviorName[] | BehaviorConfig[]; // TODO: behavior config comes from behaviors; TODO: interaction specs
[mode: string]: BehaviorName[] | BehaviorConfig[]; // TODO: behavior config comes from behaviors; TODO: interaction specs
};
mode?: string;
/** global animate */
animate?: AnimateCfg;
/** free plugins */
plugins?: {
name: string,
options: any; // TODO: configs from plugins
}[]
}

View File

@ -0,0 +1,7 @@
export interface FitViewRules {
onlyOutOfViewPort?: boolean; // Whehter fit it only when the graph is out of the view.
direction?: 'x' | 'y' | 'both'; // Axis to fit.
ratioRule?: 'max' | 'min'; // Ratio rule to fit.
}
export type GraphAlignment = 'left-top' | 'right-top' | 'left-bottom' | 'right-bottom' | 'center' | [number, number];