feat: activate relations (#4380)

* chore: fix typing to support vite

* feat: Add browser-side integration testing

* feat: add activate-relations behaviros

* feat: update typing

* feat: add activate-relations logic

* feat: add typing

* feat: add demo

* feat: update demo

---------

Co-authored-by: pomelo.lcw <pomelo.lcw@antgroup.com>
Co-authored-by: pomelo-nwu <czynwu@gmail.com>
This commit is contained in:
pomelo 2023-04-10 12:01:26 +08:00 committed by GitHub
parent eecd6786d4
commit bf06ee1378
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1183 additions and 34 deletions

View File

@ -12,6 +12,8 @@
"devDependencies": {
"@commitlint/cli": "^17.5.0",
"@commitlint/config-conventional": "^17.4.4",
"husky": "^8.0.3"
"husky": "^8.0.3",
"react-scripts": "3.1.2",
"vite": "^4.2.1"
}
}

View File

@ -31,6 +31,7 @@
"module": "es/index.js",
"types": "lib/index.d.ts",
"scripts": {
"dev":"vite",
"start": "father build --watch",
"build": "npm run clean && father build",
"ci": "npm run build && npm run coverage",

View File

@ -1,13 +1,13 @@
import { Graph as GraphLib, ID } from '@antv/graphlib';
import { GraphData, IGraph, ComboModel, ComboUserModel } from '../../types';
import { registry } from '../../stdlib';
import { getExtension } from '../../util/extension';
import { clone, isArray, isNumber, isString, isFunction, isObject } from '@antv/util';
import { NodeModel, NodeModelData, NodeUserModel, NodeUserModelData } from '../../types/node';
import { EdgeModel, EdgeModelData, EdgeUserModel, EdgeUserModelData } from '../../types/edge';
import { DataChangeType, GraphCore } from '../../types/data';
import { ITEM_TYPE } from '../../types/item';
import { clone, isArray, isFunction, isNumber, isObject, isString } from '@antv/util';
import { registery as registry } from '../../stdlib';
import { ComboModel, ComboUserModel, GraphData, IGraph } from '../../types';
import { ComboUserModelData } from '../../types/combo';
import { DataChangeType, GraphCore } from '../../types/data';
import { EdgeModel, EdgeModelData, EdgeUserModel, EdgeUserModelData } from '../../types/edge';
import { ITEM_TYPE } from '../../types/item';
import { NodeModel, NodeModelData, NodeUserModel, NodeUserModelData } from '../../types/node';
import { getExtension } from '../../util/extension';
/**
* Manages the data transform extensions;

View File

@ -0,0 +1,129 @@
import type { ID, IG6GraphEvent } from '../../types';
import { Behavior } from '../../types/behavior';
const KEYBOARD_TRIGGERS = ['shift', 'ctrl', 'alt', 'meta'] as const;
const MOUSE_TRIGGERS = ['mouseenter', 'click'] as const;
type Trigger = (typeof MOUSE_TRIGGERS)[number];
const compare = (prev: ID[], curr: ID[]) => {
const inactive = prev.filter((v) => !curr.includes(v));
const active = curr.filter((v) => !prev.includes(v));
return {
active,
inactive,
};
};
interface ActivateRelationsOptions {
/**
* Whether to allow multiple selection.
* Defaults to true.
* If set to false, `trigger` options will be ignored.
*/
multiple: boolean;
/**
* The key to pressed with mouse click to apply multiple selection.
* Defaults to `"click"`.
* Could be "click", "mouseenter".
*/
trigger: Trigger;
/**
*
* Defaults to `"selected"`.
*
*/
activeState: 'selected';
/**
* Whether allow the behavior happen on the current item.
*/
shouldBegin: (event: IG6GraphEvent) => boolean;
/**
* Whether to update item state.
* If it returns false, you may probably listen to `eventName` and
* manage states or data manually
*/
shouldUpdate: (event: IG6GraphEvent) => boolean;
}
const DEFAULT_OPTIONS: ActivateRelationsOptions = {
multiple: true,
shouldBegin: () => true,
shouldUpdate: () => true,
trigger: 'click',
activeState: 'selected',
};
export default class ActivateRelations extends Behavior {
options: ActivateRelationsOptions;
timer: number;
inactiveItems: {};
prevNodeIds: ID[];
prevEdgeIds: ID[];
constructor(options: Partial<ActivateRelationsOptions>) {
super(Object.assign({}, DEFAULT_OPTIONS, options));
// Validate options
if (options.trigger && !MOUSE_TRIGGERS.includes(options.trigger)) {
console.warn(
`G6: Invalid trigger option "${options.trigger}" for activate-relations behavior!`,
);
this.options.trigger = DEFAULT_OPTIONS.trigger;
}
this.prevEdgeIds = [];
this.prevNodeIds = [];
}
getEvents = () => {
const { trigger } = this.options;
if (trigger === 'mouseenter') {
return {
'node:mouseenter': this.setAllItemStates,
'combo:mouseenter': this.setAllItemStates,
'node:mouseleave': this.clearActiveState,
'combo:mouseleave': this.clearActiveState,
};
}
return {
'node:click': this.setAllItemStates,
'combo:click': this.setAllItemStates,
'canvas:click': this.clearActiveState,
};
};
setAllItemStates = (e: IG6GraphEvent) => {
const { itemId } = e;
const { graph } = this;
const { activeState: ACTIVE_STATE } = this.options;
if (!graph || graph.destroyed) return;
if (!this.options.shouldBegin(e)) return;
const ids = graph.getNeighborNodesData(itemId, 'both').map((item) => item.id);
const edgeIds = graph.getRelatedEdgesData(itemId, 'both').map((item) => item.id);
const nodeIds = [itemId, ...ids];
/** 数据对比,处理得到最小改动的高亮和非高亮的数据 */
const { active: activeNodeIds, inactive: inactiveNodeIds } = compare(this.prevNodeIds, nodeIds);
const { active: activeEdgeIds, inactive: inactiveEdgeIds } = compare(this.prevEdgeIds, edgeIds);
/** 节点 */
graph.setItemState(activeNodeIds, ACTIVE_STATE, true);
graph.setItemState(inactiveNodeIds, ACTIVE_STATE, false);
/** 边 */
graph.setItemState(activeEdgeIds, ACTIVE_STATE, true);
graph.setItemState(inactiveEdgeIds, ACTIVE_STATE, false);
this.prevNodeIds = nodeIds;
this.prevEdgeIds = edgeIds;
};
clearActiveState = (e: any) => {
const { activeState: ACTIVE_STATE } = this.options;
this.graph.setItemState(this.prevNodeIds, ACTIVE_STATE, false);
this.graph.setItemState(this.prevEdgeIds, ACTIVE_STATE, false);
this.prevNodeIds = [];
this.prevEdgeIds = [];
};
}

View File

@ -1,49 +1,52 @@
import { registry as layoutRegistry } from '@antv/layout';
import { Lib } from '../types/stdlib';
import DragCanvas from './behavior/drag-canvas';
import ClickSelect from "./behavior/click-select";
import ActivateRelations from './behavior/activate-relations';
import BrushSelect from './behavior/brush-select';
import ClickSelect from './behavior/click-select';
import DragCanvas from './behavior/drag-canvas';
import LassoSelect from './behavior/lasso-select';
import { DragNode } from "./behavior/drag-node";
import { comboFromNode } from './data/comboFromNode';
import { LineEdge } from './item/edge';
import { CircleNode } from './item/node';
import SpecThemeSolver from './themeSolver/spec';
import LightTheme from './theme/light';
import DarkTheme from './theme/dark';
import LightTheme from './theme/light';
import SpecThemeSolver from './themeSolver/spec';
import SubjectThemeSolver from './themeSolver/subject';
import rectSelector from './selector/rect';
import lassoSelector from './selector/lasso';
import rectSelector from './selector/rect';
const stdLib = {
transforms: {
comboFromNode,
},
themes: {
'light': LightTheme,
'dark': DarkTheme
light: LightTheme,
dark: DarkTheme,
},
themeSolvers: {
'spec': SpecThemeSolver,
'subject': SubjectThemeSolver,
spec: SpecThemeSolver,
subject: SubjectThemeSolver,
},
layouts: layoutRegistry,
behaviors: {
'activate-relations': ActivateRelations,
'drag-canvas': DragCanvas,
'drag-node': DragNode,
'click-select': ClickSelect,
'brush-select': BrushSelect,
'lasso-select': LassoSelect
'lasso-select': LassoSelect,
},
plugins: {},
nodes: {
'circle-node': CircleNode
'circle-node': CircleNode,
},
edges: {
'line-edge': LineEdge
'line-edge': LineEdge,
},
combos: {},
}
};
const useLib: Lib = {
transforms: {},
@ -58,8 +61,8 @@ const useLib: Lib = {
const utils = {
rectSelector,
lassoSelector
}
lassoSelector,
};
const registery = { useLib };
export default registery;

View File

@ -1,13 +1,14 @@
export { IGraph } from './graph';
export { GraphData } from './data';
export { NodeUserModel, NodeModel, NodeDisplayModel } from './node';
export { EdgeUserModel, EdgeModel, EdgeDisplayModel } from './edge';
export { ComboUserModel, ComboModel, ComboDisplayModel } from './combo';
export { Specification } from './spec';
export {
StandardLayoutOptions,
export type { ID } from '@antv/graphlib';
export type { ComboDisplayModel, ComboModel, ComboUserModel, ICombo } from './combo';
export type { GraphData } from './data';
export type { EdgeDisplayModel, EdgeModel, EdgeUserModel, IEdge } from './edge';
export type { IG6GraphEvent } from './event';
export type { IGraph } from './graph';
export { isImmediatelyInvokedLayoutOptions, isLayoutWorkerized } from './layout'; // function 不应该放在 types 文件下面
export type {
ImmediatelyInvokedLayoutOptions,
LayoutOptions,
isImmediatelyInvokedLayoutOptions,
isLayoutWorkerized,
StandardLayoutOptions,
} from './layout';
export type { INode, NodeDisplayModel, NodeModel, NodeUserModel } from './node';
export type { Specification } from './spec';

View File

@ -0,0 +1,840 @@
export const container = document.getElementById('container');
export const width = document.getElementById('container').clientWidth;
export const height = document.getElementById('container').clientHeight;
export const data = {
nodes: [
{
id: 'Argentina',
data: {
name: 'Argentina',
},
},
{
id: 'Australia',
data: {
name: 'Australia',
},
},
{
id: 'Belgium',
data: {
name: 'Belgium',
},
},
{
id: 'Brazil',
data: {
name: 'Brazil',
},
},
{
id: 'Colombia',
data: {
name: 'Colombia',
},
},
{
id: 'Costa Rica',
data: {
name: 'Costa Rica',
},
},
{
id: 'Croatia',
data: {
name: 'Croatia',
},
},
{
id: 'Denmark',
data: {
name: 'Denmark',
},
},
{
id: 'Egypt',
data: {
name: 'Egypt',
},
},
{
id: 'England',
data: {
name: 'England',
},
},
{
id: 'France',
data: {
name: 'France',
},
},
{
id: 'Germany',
data: {
name: 'Germany',
},
},
{
id: 'Iceland',
data: {
name: 'Iceland',
},
},
{
id: 'IR Iran',
data: {
name: 'IR Iran',
},
},
{
id: 'Japan',
data: {
name: 'Japan',
},
},
{
id: 'Korea Republic',
data: {
name: 'Korea Republic',
},
},
{
id: 'Mexico',
data: {
name: 'Mexico',
},
},
{
id: 'Morocco',
data: {
name: 'Morocco',
},
},
{
id: 'Nigeria',
data: {
name: 'Nigeria',
},
},
{
id: 'Panama',
data: {
name: 'Panama',
},
},
{
id: 'Peru',
data: {
name: 'Peru',
},
},
{
id: 'Poland',
data: {
name: 'Poland',
},
},
{
id: 'Portugal',
data: {
name: 'Portugal',
},
},
{
id: 'Russia',
data: {
name: 'Russia',
},
},
{
id: 'Saudi Arabia',
data: {
name: 'Saudi Arabia',
},
},
{
id: 'Senegal',
data: {
name: 'Senegal',
},
},
{
id: 'Serbia',
data: {
name: 'Serbia',
},
},
{
id: 'Spain',
data: {
name: 'Spain',
},
},
{
id: 'Sweden',
data: {
name: 'Sweden',
},
},
{
id: 'Switzerland',
data: {
name: 'Switzerland',
},
},
{
id: 'Tunisia',
data: {
name: 'Tunisia',
},
},
{
id: 'Uruguay',
data: {
name: 'Uruguay',
},
},
],
edges: [
{
id: '0',
target: 'Russia',
source: 'Saudi Arabia',
data: {
target_score: 5,
source_score: 0,
directed: true,
},
},
{
id: '1',
target: 'Uruguay',
source: 'Egypt',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '2',
target: 'Russia',
source: 'Egypt',
data: {
target_score: 3,
source_score: 1,
directed: true,
},
},
{
id: '3',
target: 'Uruguay',
source: 'Saudi Arabia',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '4',
target: 'Uruguay',
source: 'Russia',
data: {
target_score: 3,
source_score: 0,
directed: true,
},
},
{
id: '5',
target: 'Saudi Arabia',
source: 'Egypt',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '6',
target: 'IR Iran',
source: 'Morocco',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '7',
target: 'Portugal',
source: 'Spain',
data: {
target_score: 3,
source_score: 3,
directed: false,
},
},
{
id: '8',
target: 'Portugal',
source: 'Morocco',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '9',
target: 'Spain',
source: 'IR Iran',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '10',
target: 'IR Iran',
source: 'Portugal',
data: {
target_score: 1,
source_score: 1,
directed: false,
},
},
{
id: '11',
target: 'Spain',
source: 'Morocco',
data: {
target_score: 2,
source_score: 2,
directed: false,
},
},
{
id: '12',
target: 'France',
source: 'Australia',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '13',
target: 'Denmark',
source: 'Peru',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '14',
target: 'Denmark',
source: 'Australia',
data: {
target_score: 1,
source_score: 1,
directed: false,
},
},
{
id: '15',
target: 'France',
source: 'Peru',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '16',
target: 'Denmark',
source: 'France',
data: {
target_score: 0,
source_score: 0,
directed: false,
},
},
{
id: '17',
target: 'Peru',
source: 'Australia',
data: {
target_score: 2,
source_score: 0,
directed: true,
},
},
{
id: '18',
target: 'Argentina',
source: 'Iceland',
data: {
target_score: 1,
source_score: 1,
},
},
{
id: '19',
target: 'Croatia',
source: 'Nigeria',
data: {
target_score: 2,
source_score: 0,
directed: true,
},
},
{
id: '20',
target: 'Croatia',
source: 'Argentina',
data: {
target_score: 3,
source_score: 0,
directed: true,
},
},
{
id: '21',
target: 'Nigeria',
source: 'Iceland',
data: {
target_score: 2,
source_score: 0,
directed: true,
},
},
{
id: '22',
target: 'Argentina',
source: 'Nigeria',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '23',
target: 'Croatia',
source: 'Iceland',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '24',
target: 'Serbia',
source: 'Costa Rica',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '25',
target: 'Brazil',
source: 'Switzerland',
data: {
target_score: 1,
source_score: 1,
directed: false,
},
},
{
id: '26',
target: 'Brazil',
source: 'Costa Rica',
data: {
target_score: 2,
source_score: 0,
directed: true,
},
},
{
id: '27',
target: 'Switzerland',
source: 'Serbia',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '28',
target: 'Brazil',
source: 'Serbia',
data: {
target_score: 2,
source_score: 0,
directed: true,
},
},
{
id: '29',
target: 'Switzerland',
source: 'Costa Rica',
data: {
target_score: 2,
source_score: 2,
directed: false,
},
},
{
id: '30',
target: 'Mexico',
source: 'Germany',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '31',
target: 'Sweden',
source: 'Korea Republic',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '32',
target: 'Mexico',
source: 'Korea Republic',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '33',
target: 'Germany',
source: 'Sweden',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '34',
target: 'Korea Republic',
source: 'Germany',
data: {
target_score: 2,
source_score: 0,
directed: true,
},
},
{
id: '35',
target: 'Sweden',
source: 'Mexico',
data: {
target_score: 3,
source_score: 0,
directed: true,
},
},
{
id: '36',
target: 'Belgium',
source: 'Panama',
data: {
target_score: 3,
source_score: 0,
directed: true,
},
},
{
id: '37',
target: 'England',
source: 'Tunisia',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '38',
target: 'Belgium',
source: 'Tunisia',
data: {
target_score: 5,
source_score: 2,
directed: true,
},
},
{
id: '39',
target: 'England',
source: 'Panama',
data: {
target_score: 6,
source_score: 1,
directed: true,
},
},
{
id: '40',
target: 'Belgium',
source: 'England',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '41',
target: 'Tunisia',
source: 'Panama',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '42',
target: 'Japan',
source: 'Colombia',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '43',
target: 'Senegal',
source: 'Poland',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '44',
target: 'Japan',
source: 'Senegal',
data: {
target_score: 2,
source_score: 2,
directed: false,
},
},
{
id: '45',
target: 'Colombia',
source: 'Poland',
data: {
target_score: 3,
source_score: 0,
directed: true,
},
},
{
id: '46',
target: 'Poland',
source: 'Japan',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '47',
target: 'Colombia',
source: 'Senegal',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '48',
target: 'Uruguay',
source: 'Portugal',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '49',
target: 'France',
source: 'Argentina',
data: {
target_score: 4,
source_score: 3,
directed: true,
},
},
{
id: '50',
target: 'Russia',
source: 'Spain',
data: {
target_score: 5,
source_score: 4,
directed: true,
},
},
{
id: '51',
target: 'Croatia',
source: 'Denmark',
data: {
target_score: 4,
source_score: 3,
directed: true,
},
},
{
id: '52',
target: 'Brazil',
source: 'Mexico',
data: {
target_score: 2,
source_score: 0,
directed: true,
},
},
{
id: '53',
target: 'Belgium',
source: 'Japan',
data: {
target_score: 3,
source_score: 2,
directed: true,
},
},
{
id: '54',
target: 'Sweden',
source: 'Switzerland',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '55',
target: 'England',
source: 'Colombia',
data: {
target_score: 4,
source_score: 3,
directed: true,
},
},
{
id: '56',
target: 'France',
source: 'Uruguay',
data: {
target_score: 2,
source_score: 0,
directed: true,
},
},
{
id: '57',
target: 'Belgium',
source: 'Brazil',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '58',
target: 'Croatia',
source: 'Russia',
data: {
target_score: 6,
source_score: 5,
directed: true,
},
},
{
id: '59',
target: 'England',
source: 'Sweden',
data: {
target_score: 2,
source_score: 0,
directed: true,
},
},
{
id: '60',
target: 'France',
source: 'Belgium',
data: {
target_score: 1,
source_score: 0,
directed: true,
},
},
{
id: '61',
target: 'Croatia',
source: 'England',
data: {
target_score: 2,
source_score: 1,
directed: true,
},
},
{
id: '62',
target: 'Belgium',
source: 'England',
data: {
target_score: 2,
source_score: 0,
directed: true,
},
},
{
id: '63',
target: 'France',
source: 'Croatia',
data: {
target_score: 4,
source_score: 2,
directed: true,
},
},
],
};

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>G6: Preview</title>
</head>
<body>
<div id="app">
<label for="">选择要测试的DEMO </label> <select id="select" style="height:40px;cursor: pointer;"></select>
<div id="container" style="height: 500px;width:100%"></div>
</div>
<script type="module" src="./main.ts"></script>
</body>
</html>

View File

@ -0,0 +1,41 @@
import G6 from '../../../src/index';
import { container, height, width } from '../../datasets/const';
export default () => {
return new G6.Graph({
container,
width,
height,
type: 'graph',
layout: {
type: 'grid',
},
node: {
labelShape: {
text: {
fields: ['id'],
formatter: (model) => model.id,
},
},
},
data: {
nodes: [
{ id: 'node1', data: {} },
{ id: 'node2', data: {} },
{ id: 'node3', data: {} },
{ id: 'node4', data: {} },
{ id: 'node5', data: {} },
],
edges: [
{ id: 'edge1', source: 'node1', target: 'node2', data: {} },
{ id: 'edge2', source: 'node1', target: 'node3', data: {} },
{ id: 'edge3', source: 'node1', target: 'node4', data: {} },
{ id: 'edge4', source: 'node2', target: 'node3', data: {} },
{ id: 'edge5', source: 'node3', target: 'node4', data: {} },
{ id: 'edge6', source: 'node4', target: 'node5', data: {} },
],
},
modes: {
default: [{ type: 'activate-relations', trigger: 'click' }],
},
});
};

View File

@ -0,0 +1,25 @@
import G6 from '../../../src/index';
import { container, height, width } from '../../datasets/const';
export default () => {
return new G6.Graph({
container,
width,
height,
type: 'graph',
layout: {
type: 'grid',
},
data: {
nodes: [
{ id: 'node1', data: {} },
{ id: 'node2', data: {} },
{ id: 'node3', data: {} },
{ id: 'node4', data: {} },
],
edges: [{ id: 'edge1', source: 'node1', target: 'node2', data: {} }],
},
modes: {
default: ['brush-select'],
},
});
};

View File

@ -0,0 +1,25 @@
import G6 from '../../../src/index';
import { container, height, width } from '../../datasets/const';
export default () => {
return new G6.Graph({
container,
width,
height,
type: 'graph',
layout: {
type: 'grid',
},
data: {
nodes: [
{ id: 'node1', data: {} },
{ id: 'node2', data: {} },
{ id: 'node3', data: {} },
{ id: 'node4', data: {} },
],
edges: [{ id: 'edge1', source: 'node1', target: 'node2', data: {} }],
},
modes: {
default: ['click-select'],
},
});
};

View File

@ -0,0 +1,10 @@
import behaviors_activateRelations from './behaviors/activate-relations';
import behaviors_brush_select from './behaviors/brush-select';
import behaviors_click_select from './behaviors/click-select';
import layouts_circular from './layouts/circular';
export {
behaviors_activateRelations,
layouts_circular,
behaviors_brush_select,
behaviors_click_select,
};

View File

@ -0,0 +1,17 @@
import G6 from '../../../src/index';
import { container, data, height, width } from '../../datasets/const';
export default () => {
return new G6.Graph({
container,
width,
height,
type: 'graph',
data,
layout: {
type: 'circular',
center: [250, 250],
radius: 200,
},
});
};

28
packages/g6/tests/main.ts Normal file
View File

@ -0,0 +1,28 @@
import * as graphs from './intergration/index';
const SelectGraph = document.getElementById('select') as HTMLSelectElement;
let firstKey;
console.log('firstKey', firstKey);
const Options = Object.keys(graphs).map((key, index) => {
const option = document.createElement('option');
if (index === 0) {
firstKey = key;
}
option.value = key;
option.textContent = key;
return option;
});
SelectGraph.replaceChildren(...Options);
SelectGraph.onchange = (e) => {
//@ts-ignore
const { value } = e.target;
console.log(value);
history.pushState({ value }, '', `?name=${value}`);
const container = document.getElementById('container');
container.replaceChildren('');
graphs[value]();
};
// 初始化
graphs[firstKey]();

View File

@ -0,0 +1,9 @@
import { defineConfig } from 'vite';
export default defineConfig({
root: './tests',
server: {
port: 8080,
open: '/',
},
});