fix: update edge with false endArrow and startArrow; fix: node and edge state style with update problem; fix: import lib problem; fix: tooltip for combo;

This commit is contained in:
Yanyan-Wang 2020-11-26 18:05:44 +08:00 committed by Yanyan Wang
parent e3b4987f18
commit 11a1a8f2a6
82 changed files with 426 additions and 729 deletions

View File

@ -1,5 +1,16 @@
# ChangeLog
#### 4.0.2
- fix: node and edge state style with update problem;
- fix: import lib problem;
- fix: import node module problem;
- fix: hidden shapes show up after zoom-canvas or drag-canvas with enableOptimize;
- fix: tooltip for combo;
- fix: update edge with false endArrow and startArrow;
#### 4.0.1
- fix: glslang problem;
#### 4.0.0-beta.0
- feat: fruchterman and gforce layout with gpu;
- feat: gforce;

View File

@ -1,6 +1,6 @@
{
"name": "@antv/g6",
"version": "4.0.1",
"version": "4.0.2",
"description": "A Graph Visualization Framework in JavaScript",
"keywords": [
"antv",
@ -47,7 +47,8 @@
"site:build": "npm run site:clean && GATSBY=true gatsby build --prefix-paths",
"site:clean": "gatsby clean",
"site:develop": "GATSBY=true gatsby develop --open",
"site:deploy": "npm run site:build && gh-pages -d public",
"site:deploy": "npm run site:build && npm run site:copy-mirror-action && gh-pages -d public",
"site:copy-mirror-action": "mkdir -p public/.github/workflows && cp .github/workflows/mirror.yml public/.github/workflows",
"start": "npm run site:develop",
"test": "jest",
"test-live": "DEBUG_MODE=1 jest --watch ./tests/unit/graph/graph-watermarker-spec.ts",

View File

@ -1,6 +1,7 @@
import LinkedList from '../linked-list';
export default class Stack {
private linkedList: LinkedList;
private maxStep: number;

View File

@ -1,4 +1,4 @@
import { clone, each, wrapBehavior } from '@antv/util/lib';
import { clone, each, wrapBehavior } from '@antv/util';
import { BehaviorOption } from '../types';
import behaviorOption from './behaviorOption';

View File

@ -1,4 +1,4 @@
import each from '@antv/util/lib/each';
import { each } from '@antv/util';
import { IGraph } from '../interface/graph';
import { G6Event } from '../types';

View File

@ -1,4 +1,4 @@
import each from '@antv/util/lib/each';
import { each } from '@antv/util';
import { G6Event, IG6GraphEvent } from '../types';
const DEFAULT_TRIGGER = 'shift';

View File

@ -7,7 +7,7 @@ import { G6Event, IG6GraphEvent, Item, ComboConfig } from '../types';
import { calculationItemsBBox } from '../util/base';
import Global from '../global';
import { IGraph } from '../interface/graph';
import { each } from '@antv/util/lib';
import { each } from '@antv/util';
import { IGroup } from '@antv/g-base/lib/interfaces';
import { ICombo, INode } from '../interface/item';

View File

@ -6,7 +6,7 @@
* @Description: Behavior
*/
import { Point } from '@antv/g-base/lib/types';
import { deepMix, clone } from '@antv/util/lib';
import { deepMix, clone } from '@antv/util';
import { INode, ICombo } from '../interface/item';
import { G6Event, IG6GraphEvent, Item, NodeConfig } from '../types';
import Global from '../global';

View File

@ -1,4 +1,4 @@
import each from '@antv/util/lib/each';
import { each } from '@antv/util';
import Behavior from './behavior';
import DragCanvas from './drag-canvas';
import DragNode from './drag-node';

View File

@ -1,5 +1,4 @@
import modifyCSS from '@antv/dom-util/lib/modify-css';
import createDom from '@antv/dom-util/lib/create-dom';
import { modifyCSS, createDom } from '@antv/dom-util';
import { IG6GraphEvent } from '../types';
export default {

View File

@ -7,7 +7,7 @@ const textColor = 'rgb(0, 0, 0)';
const colorSet = getColorsWithSubjectColor(subjectColor, backColor);
export default {
version: '4.0.1',
version: '4.0.2',
rootContainerClassName: 'root-container',
nodeContainerClassName: 'node-container',
edgeContainerClassName: 'edge-container',

View File

@ -1,14 +1,12 @@
import addEventListener from '@antv/dom-util/lib/add-event-listener';
import { addEventListener } from '@antv/dom-util';
import Canvas from '@antv/g-base/lib/abstract/canvas';
import Group from '@antv/g-canvas/lib/group';
import ShapeBase from '@antv/g-canvas/lib/shape/base';
import each from '@antv/util/lib/each';
import isNil from '@antv/util/lib/is-nil';
import wrapBehavior from '@antv/util/lib/wrap-behavior';
import { Group, Shape } from '@antv/g-canvas';
import { each, isNil, wrapBehavior } from '@antv/util';
import Graph from '../graph';
import { IG6GraphEvent, Matrix, Item } from '../../types';
import { cloneEvent, isViewportChanged } from '../../util/base';
type ShapeBase = Shape.Base;
type Fun = () => void;
// const EVENTS = [

View File

@ -1,11 +1,5 @@
import Group from '@antv/g-canvas/lib/group';
import clone from '@antv/util/lib/clone';
import deepMix from '@antv/util/lib/deep-mix';
import each from '@antv/util/lib/each';
import isArray from '@antv/util/lib/is-array';
import isObject from '@antv/util/lib/is-object';
import isString from '@antv/util/lib/is-string';
import upperFirst from '@antv/util/lib/upper-first';
import { Group } from '@antv/g-canvas';
import { clone, deepMix, each, isArray, isObject, isString, upperFirst } from '@antv/util';
import Edge from '../../item/edge';
import Node from '../../item/node';
import Combo from '../../item/combo';
@ -204,6 +198,8 @@ export default class ItemController {
const mapper = graph.get(type + MAPPER_SUFFIX);
const model = item.getModel();
const isOnlyMove = item.isOnlyMove(cfg);
if (mapper) {
const result: ModelConfig = deepMix({}, model, cfg);
const mappedModel: ModelConfig = mapper(result);
@ -248,11 +244,13 @@ export default class ItemController {
}
(item as IEdge).setTarget(target);
}
item.update(cfg);
}
item.update(cfg);
// item.update(cfg);
if (type === NODE || type === COMBO) {
item.update(cfg, isOnlyMove);
const edges: IEdge[] = (item as INode).getEdges();
each(edges, (edge: IEdge) => {
edge.refresh();

View File

@ -272,6 +272,7 @@ export default class LayoutController {
const offScreenCanvas = document.createElement('canvas');
const gpuWorkerAbility = isGPU && typeof window !== 'undefined'
// eslint-disable-next-line @typescript-eslint/dot-notation
&& window.navigator && !navigator[`gpu`] // WebGPU 还不支持 OffscreenCanvas
&& 'OffscreenCanvas' in window
&& 'transferControlToOffscreen' in offScreenCanvas;

View File

@ -1,6 +1,4 @@
import each from '@antv/util/lib/each';
import isArray from '@antv/util/lib/is-array';
import isString from '@antv/util/lib/is-string';
import { each, isArray, isString } from '@antv/util';
import Behavior from '../../behavior/behavior';
import { IBehavior } from '../../interface/behavior';
import { IGraph } from '../../interface/graph';

View File

@ -1,5 +1,4 @@
import each from '@antv/util/lib/each';
import isString from '@antv/util/lib/is-string';
import { each, isString } from '@antv/util';
import { Item, States } from '../../types';
import Graph from '../graph';
import { INode } from '../../interface/item';

View File

@ -1,13 +1,12 @@
import Canvas from '@antv/g-base/lib/abstract/canvas';
import { Point } from '@antv/g-base/lib/types';
import Group from '@antv/g-canvas/lib/group';
import isNumber from '@antv/util/lib/is-number';
import isString from '@antv/util/lib/is-string';
import { Group } from '@antv/g-canvas';
import { isNumber, isString } from '@antv/util';
import { Item, Matrix, Padding, GraphAnimateConfig } from '../../types';
import { formatPadding } from '../../util/base';
import { applyMatrix, invertMatrix } from '../../util/math';
import Graph from '../graph';
import modifyCSS from '@antv/dom-util/lib/modify-css';
import { modifyCSS } from '@antv/dom-util';
export default class ViewController {
private graph: Graph;

View File

@ -1,10 +1,10 @@
import EventEmitter from '@antv/event-emitter';
import { IGroup } from '@antv/g-base/lib/interfaces';
import { BBox, Point } from '@antv/g-base/lib/types';
import GCanvas from '@antv/g-canvas/lib/canvas';
import GSVGCanvas from '@antv/g-svg/lib/canvas';
import { mat3 } from '@antv/matrix-util/lib';
import { clone, deepMix, each, isPlainObject, isString, isNumber, groupBy } from '@antv/util';
import { Point } from '@antv/g-base/lib/types';
import { Canvas as GCanvas } from '@antv/g-canvas';
import { Canvas as GSVGCanvas } from '@antv/g-svg';
import { mat3 } from '@antv/matrix-util';
import { clone, deepMix, each, isPlainObject, isString, isNumber } from '@antv/util';
import { IGraph, DataUrlType } from '../interface/graph';
import { IEdge, INode, ICombo } from '../interface/item';
import {
@ -40,7 +40,7 @@ import {
ViewController,
} from './controller';
import PluginBase from '../plugins/base';
import createDom from '@antv/dom-util/lib/create-dom';
import { createDom } from '@antv/dom-util';
import { plainCombosToTrees, traverseTree, reconstructTree, traverseTreeUp } from '../util/graphic';
import degree from '../algorithm/degree';
import Stack from '../algorithm/structs/stack';

View File

@ -1,6 +1,6 @@
import { Point } from '@antv/g-base/lib/types';
import Hierarchy from '@antv/hierarchy/lib';
import { each, isString } from '@antv/util/lib';
import Hierarchy from '@antv/hierarchy';
import { each, isString } from '@antv/util';
import { ITreeGraph } from '../interface/graph';
import { GraphData, Item, NodeConfig, ShapeStyle, TreeGraphData, GraphOptions } from '../types';
import { radialLayout, traverseTree } from '../util/graphic';

View File

@ -1,5 +1,5 @@
import GraphEvent from '@antv/g-base/lib/event/graph-event';
import Canvas from '@antv/g-canvas/lib/canvas';
import { Event as GraphEvent } from '@antv/g-base';
import { Canvas } from '@antv/g-canvas';
import { G6Event, IG6GraphEvent, IShapeBase, Item } from '../types';
import { IGraph } from './graph';

View File

@ -1,7 +1,7 @@
/* eslint @typescript-eslint/no-use-before-define: 0 */
import { IGroup } from '@antv/g-base/lib/interfaces';
import { Point } from '@antv/g-base/lib/types';
import Group from '@antv/g-canvas/lib/group';
import { Group } from '@antv/g-canvas';
import {
IBBox,
IPoint,
@ -162,8 +162,9 @@ export interface IItemBase {
* model
* @internal Graph 使 graph.update
* @param {Object} cfg
* @param {boolean} onlyMove node combo true
*/
update(cfg: ModelConfig): void;
update(cfg: ModelConfig, onlyMove?: boolean): void;
/**
*

View File

@ -1,4 +1,4 @@
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { IPoint, Item, LabelStyle, ModelConfig, ShapeStyle } from '../types';

View File

@ -1,10 +1,10 @@
import { ICombo, INode, IItemBaseConfig } from '../interface/item';
import Group from '@antv/g-canvas/lib/group';
import { Group } from '@antv/g-canvas';
import Node from './node';
import { ComboConfig, IBBox, IShapeBase } from '../types';
import Global from '../global';
import { getBBox } from '../util/graphic';
import isNumber from '@antv/util/lib/is-number';
import { isNumber } from '@antv/util';
const CACHE_BBOX = 'bboxCache';
const CACHE_CANVAS_BBOX = 'bboxCanvasCache';

View File

@ -207,7 +207,7 @@ export default class Edge extends Item implements IEdge {
* path
* @param {object} cfg
*/
public update(cfg: EdgeConfig) {
public update(cfg: EdgeConfig, onlyMove: boolean = false) {
const model: EdgeConfig = this.get('model');
const oriVisible = model.visible;
const cfgVisible = cfg.visible;

View File

@ -1,4 +1,4 @@
import Group from '@antv/g-canvas/lib/group';
import { Group } from '@antv/g-canvas';
import {
each,
isNil,
@ -8,6 +8,7 @@ import {
uniqueId,
mix,
deepMix,
isArray,
} from '@antv/util';
import { IItemBase, IItemBaseConfig } from '../interface/item';
import Shape from '../shape/shape';
@ -26,6 +27,7 @@ import {
import { getBBox } from '../util/graphic';
import { translate } from '../util/math';
import { IGroup } from '@antv/g-base/lib/interfaces';
import Global from '../global';
const CACHE_BBOX = 'bboxCache';
const CACHE_CANVAS_BBOX = 'bboxCanvasCache';
@ -211,22 +213,34 @@ export default class ItemBase implements IItemBase {
const children = group.get('children');
const keyShape: IShapeBase = this.getKeyShape();
const self = this;
const keyShapeName = keyShape.get('name');
each(children, (child) => {
const name = child.get('name');
if (name) {
if (name && name !== keyShapeName) {
originStyles[name] = self.getShapeStyleByName(name);
} else {
const keyShapeName = keyShape.get('name');
const keyShapeStyle = self.getShapeStyleByName();
if (!keyShapeName) {
Object.assign(originStyles, keyShapeStyle);
} else {
originStyles[keyShapeName] = keyShapeStyle;
}
}
});
const model = this.getModel();
const shapeFactory = Shape.getFactory(this.get('type'));
const shapeOptions = shapeFactory.getShape().getOptions(model);
const defaultStyle = shapeOptions.style;
const size = shapeOptions.size;
const itemType = this.get('type');
if (itemType === 'edge') {
if (!defaultStyle.lineWidth) defaultStyle.lineWidth = size || Global.defaultEdge.size;
} else if (itemType === 'node') {
if (!defaultStyle.r) defaultStyle.r = size / 2 || Global.defaultNode.size / 2;
if (!defaultStyle.width) defaultStyle.r = (isArray(size) ? size[0] : size) || Global.defaultNode.size / 2;
if (!defaultStyle.height) defaultStyle.r = (isArray(size) ? size[1] : size) || Global.defaultNode.size / 2;
}
if (!keyShapeName) {
Object.assign(originStyles, defaultStyle);
} else {
originStyles[keyShapeName] = defaultStyle;
}
const drawOriginStyle = this.getOriginStyle();
let styles = {};
if (cfg) {
@ -371,6 +385,10 @@ export default class ItemBase implements IItemBase {
public getCurrentStatesStyle(): ShapeStyle {
const self = this;
let styles = {};
const states = self.getStates();
if (!states || !states.length) {
return this.getOriginStyle();
}
each(self.getStates(), (state) => {
styles = Object.assign(styles, self.getStateStyle(state));
});
@ -545,7 +563,7 @@ export default class ItemBase implements IItemBase {
* @internal Graph 使 graph.update
* @param {Object} cfg
*/
public update(cfg: ModelConfig) {
public update(cfg: ModelConfig, onlyMove: boolean = false) {
const model: ModelConfig = this.get('model');
const oriVisible = model.visible;
const cfgVisible = cfg.visible;
@ -566,7 +584,8 @@ export default class ItemBase implements IItemBase {
Object.assign(model, cfg);
// isOnlyMove 仅用于node
const onlyMove = this.isOnlyMove(cfg);
// const onlyMove = this.isOnlyMove(cfg);
// 仅仅移动位置时,既不更新,也不重绘
if (onlyMove) {
this.updatePosition(cfg);

View File

@ -1,6 +1,4 @@
import each from '@antv/util/lib/each';
import isNil from '@antv/util/lib/is-nil';
import mix from '@antv/util/lib/mix';
import { each, isNil, mix } from '@antv/util';
import { IEdge, INode } from '../interface/item';
import { IPoint, IShapeBase, NodeConfig } from '../types';
import {

View File

@ -5,12 +5,9 @@
*/
import { EdgeConfig, IPointTuple, NodeConfig, NodeIdxMap } from '../types';
import isArray from '@antv/util/lib/is-array';
import isString from '@antv/util/lib/is-string';
import { isArray, isString, isNumber } from '@antv/util';
import { BaseLayout } from './layout';
import { getDegree } from '../util/math';
import { isNumber } from '@antv/util';
type Node = NodeConfig & {
[key: string]: number;

View File

@ -5,9 +5,8 @@
import dagre from 'dagre';
import isArray from '@antv/util/lib/is-array';
import { isArray, isNumber } from '@antv/util';
import { BaseLayout } from './layout';
import { isNumber } from '@antv/util';
/**
*

View File

@ -8,10 +8,7 @@ import { GraphData, IPointTuple } from '../../types';
import * as d3Force from 'd3-force';
import forceInABox from './force-in-a-box';
import isArray from '@antv/util/lib/is-array';
import isFunction from '@antv/util/lib/is-function';
import isNumber from '@antv/util/lib/is-number';
import mix from '@antv/util/lib/mix';
import { isArray, isFunction, isNumber, mix } from '@antv/util';
import { BaseLayout } from '../layout';
import { LAYOUT_MESSAGE } from '../worker/layoutConst';

View File

@ -106,6 +106,7 @@ export default class GForceLayout extends BaseLayout {
enableTick: true
};
}
/**
*
*/
@ -239,8 +240,9 @@ export default class GForceLayout extends BaseLayout {
iter++;
if (iter > maxIteration) window.clearInterval(self.timeInterval);
}, 0);
self.onLayoutEnd && self.onLayoutEnd();
if (self.onLayoutEnd) self.onLayoutEnd();
}
public calRepulsive(accArray, nodes) {
const self = this;
// const nodes = self.nodes;
@ -277,6 +279,7 @@ export default class GForceLayout extends BaseLayout {
});
});
}
public calAttractive(accArray, edges) {
const self = this;
// const edges = self.edges;
@ -353,6 +356,7 @@ export default class GForceLayout extends BaseLayout {
velArray[2 * i + 1] = vy;
});
}
public updatePosition(velArray, stepInterval, nodes) {
const self = this;
// const nodes = self.nodes;
@ -363,6 +367,7 @@ export default class GForceLayout extends BaseLayout {
node.y += distY;
});
}
public stop() {
if (this.timeInterval && typeof window !== 'undefined') {
window.clearInterval(this.timeInterval);

View File

@ -231,12 +231,14 @@ export default class FruchtermanGPULayout extends BaseLayout {
const execute = async () => {
for (let i = 0; i < maxIteration; i++) {
// eslint-disable-next-line no-await-in-loop
await kernelFruchterman.execute();
if (clustering) {
kernelCluster.setBinding({
u_Data: kernelFruchterman,
});
// eslint-disable-next-line no-await-in-loop
await kernelCluster.execute();
kernelFruchterman.setBinding({
u_ClusterCenters: kernelCluster,
@ -265,7 +267,7 @@ export default class FruchtermanGPULayout extends BaseLayout {
node.y = y;
});
}
onLayoutEnd && onLayoutEnd();
if (onLayoutEnd) onLayoutEnd();
}
execute();

View File

@ -296,6 +296,7 @@ export default class GForceGPULayout extends BaseLayout {
// });
// }
// eslint-disable-next-line no-await-in-loop
await kernelGForce.execute();
// midRes = await kernelGForce.getOutput();
@ -306,6 +307,7 @@ export default class GForceGPULayout extends BaseLayout {
u_Data: kernelGForce
});
// eslint-disable-next-line no-await-in-loop
await kernelAveMovement.execute();
// 更新衰减函数

View File

@ -6,9 +6,8 @@
import { EdgeConfig, IPointTuple, NodeConfig, NodeIdxMap } from '../types';
import isString from '@antv/util/lib/is-string';
import { isArray, isString, isNumber } from '@antv/util';
import { BaseLayout } from './layout';
import { isArray, isNumber } from '@antv/util';
import { getDegree } from '../util/math';
import { isNaN } from '../util/base';

View File

@ -3,7 +3,7 @@
* @author shiwu.wyy@antfin.com
*/
import each from '@antv/util/lib/each';
import { each } from '@antv/util';
import Layout from './layout';
import Circular from './circular';

View File

@ -6,9 +6,7 @@
import { EdgeConfig, GraphData, IPointTuple, NodeConfig, ComboConfig } from '../types';
import { ILayout } from '../interface/layout';
// import augment from '@antv/util/lib/augment';
import each from '@antv/util/lib/each';
import mix from '@antv/util/lib/mix';
import { each, mix } from '@antv/util';
/**
*

View File

@ -5,10 +5,7 @@
import { IPointTuple, NodeConfig, Matrix } from '../../types';
import isArray from '@antv/util/lib/is-array';
import isNumber from '@antv/util/lib/is-number';
import isString from '@antv/util/lib/is-string';
import isFunction from '@antv/util/lib/is-function';
import { isArray, isFunction, isNumber, isString } from '@antv/util';
import { floydWarshall, getAdjMatrix } from '../../util/math';
import { isNaN } from '../../util/base';

View File

@ -1,6 +1,4 @@
import deepMix from '@antv/util/lib/deep-mix';
import each from '@antv/util/lib/each';
import wrapBehavior from '@antv/util/lib/wrap-behavior';
import { wrapBehavior, each, deepMix } from '@antv/util';
import Graph from '../graph/graph';
import { IG6GraphEvent } from '../types';

View File

@ -1,4 +1,4 @@
import { clone } from '@antv/util/lib';
import { clone } from '@antv/util';
import { IG6GraphEvent, ShapeStyle } from '../../types';
import Graph from '../../graph/graph';
import Base from '../base';

View File

@ -1,4 +1,4 @@
import { clone } from '@antv/util/lib';
import { clone } from '@antv/util';
import { IG6GraphEvent, ShapeStyle } from '../../types';
import Graph from '../../graph/graph';
import Base from '../base';

View File

@ -1,9 +1,8 @@
import createDOM from '@antv/dom-util/lib/create-dom';
import modifyCSS from '@antv/dom-util/lib/modify-css';
import { modifyCSS, createDom } from '@antv/dom-util';
import Canvas from '@antv/g-base/lib/abstract/canvas';
import { IGraph } from '../../interface/graph';
import { ViewPortEventParam } from '../../types';
import Base, { IPluginBaseConfig } from '../base';
import Base from '../base';
interface GridConfig {
img?: string;
@ -29,11 +28,11 @@ export default class Grid extends Base {
const height: number = graph.get<number>('height');
const img = this.get('img') || GRID_PNG;
const container: HTMLDivElement = createDOM(
const container: HTMLDivElement = createDom(
`<div class='g6-grid-container' style="position: absolute; left:0;top:0;right:0;bottom:0;overflow: hidden;z-index: -1;"></div>`,
);
const gridContainer: HTMLDivElement = createDOM(
const gridContainer: HTMLDivElement = createDom(
`<div
class='g6-grid'
style='position:absolute;

View File

@ -1,12 +1,10 @@
import Base, { IPluginBaseConfig } from '../base';
import isString from '@antv/util/lib/is-string';
import createDOM from '@antv/dom-util/lib/create-dom';
import modifyCSS from '@antv/dom-util/lib/modify-css';
import isNil from '@antv/util/lib/is-nil';
import { isString, isNil } from '@antv/util';
import { modifyCSS, createDom } from '@antv/dom-util';
import Graph from '../../graph/graph';
import { ShapeStyle } from '../../types';
import { Point } from '@antv/g-math/lib/types';
import GraphEvent from '@antv/g-base/lib/event/graph-event';
import { Event as GraphEvent } from '@antv/g-base';
import { mat3 } from '@antv/matrix-util';
import { applyMatrix } from '../../util/math';
@ -85,7 +83,7 @@ export default class ImageMiniMap extends Base {
if (isString(containerDOM)) {
containerDOM = document.getElementById(containerDOM) as HTMLDivElement;
}
const viewport = createDOM(
const viewport = createDom(
`<div class=${cfgs.viewportClassName}
style='position:absolute;
left:0;
@ -347,7 +345,7 @@ export default class ImageMiniMap extends Base {
self.set('width', cWidth);
}
const container: HTMLElement = createDOM(
const container: HTMLElement = createDom(
`<div class='${className}' style='width: ${cWidth}px; height: ${cHeight}px; overflow: hidden; position: relative;'></div>`, //
);
@ -363,17 +361,17 @@ export default class ImageMiniMap extends Base {
self.set('container', container);
const containerDOM = createDOM(
const containerDOM = createDom(
`<div class="g6-minimap-container" style="position: relative; width: 100%; height: 100%; text-align: center; display: table;"></div>`,
);
container.appendChild(containerDOM);
const span = createDOM(`<span style="display: table-cell; vertical-align: middle; "></span>`);
const span = createDom(`<span style="display: table-cell; vertical-align: middle; "></span>`);
containerDOM.appendChild(span);
self.set('containerDOM', containerDOM);
self.set('containerSpan', span);
const img = createDOM(
const img = createDom(
`<img alt="" src="${this.get(
'graphImg',
)}" style="display: inline-block;" ondragstart="return false;" onselectstart="return false;"/>`,
@ -454,7 +452,7 @@ export default class ImageMiniMap extends Base {
oriImgDOM.remove();
self.set('graphImg', img);
const imgDOM = createDOM(
const imgDOM = createDom(
`<img alt="" src="${img}" style="display: inline-block;" ondragstart="return false;" onselectstart="return false;"/>`,
);
self.set('imgDOM', imgDOM);

View File

@ -1,6 +1,5 @@
import modifyCSS from '@antv/dom-util/lib/modify-css';
import createDOM from '@antv/dom-util/lib/create-dom';
import isString from '@antv/util/lib/is-string';
import { modifyCSS, createDom } from '@antv/dom-util';
import { isString } from '@antv/util';
import insertCss from 'insert-css';
import Graph from '../../graph/graph';
import { IG6GraphEvent, Item } from '../../types';
@ -70,7 +69,7 @@ export default class Menu extends Base {
public init() {
const className = this.get('className');
const menu = createDOM(`<div class=${className || 'g6-component-contextmenu'}></div>`);
const menu = createDom(`<div class=${className || 'g6-component-contextmenu'}></div>`);
modifyCSS(menu, { top: '0px', position: 'absolute', visibility: 'hidden' });
let container: HTMLDivElement | null = this.get('container');
if (!container) {

View File

@ -1,16 +1,13 @@
import GCanvas from '@antv/g-canvas/lib/canvas';
import GSVGCanvas from '@antv/g-svg/lib/canvas';
import { Canvas as GCanvas } from '@antv/g-canvas';
import { Canvas as GSVGCanvas } from '@antv/g-svg';
import Base, { IPluginBaseConfig } from '../base';
import isString from '@antv/util/lib/is-string';
import createDOM from '@antv/dom-util/lib/create-dom';
import modifyCSS from '@antv/dom-util/lib/modify-css';
import isNil from '@antv/util/lib/is-nil';
import each from '@antv/util/lib/each';
import { isString, isNil, each } from '@antv/util';
import { createDom, modifyCSS } from '@antv/dom-util';
import Graph from '../../graph/graph';
import { Matrix, ShapeStyle } from '../../types';
import { transform } from '@antv/matrix-util';
import { Point } from '@antv/g-math/lib/types';
import GraphEvent from '@antv/g-base/lib/event/graph-event';
import { Event as GraphEvent } from '@antv/g-base';
import { debounce } from '@antv/util';
const { max } = Math;
@ -77,7 +74,7 @@ export default class MiniMap extends Base {
const canvas = this.get('canvas');
const containerDOM = canvas.get('container');
const viewport = createDOM(`
const viewport = createDom(`
<div
class=${cfgs.viewportClassName}
style='position:absolute;
@ -477,7 +474,7 @@ export default class MiniMap extends Base {
const size: number[] = self.get('size');
const className: string = self.get('className');
let parentNode: string | HTMLElement = self.get('container');
const container: HTMLElement = createDOM(
const container: HTMLElement = createDom(
`<div class='${className}' style='width: ${size[0]}px; height: ${size[1]}px; overflow: hidden'></div>`,
);
@ -493,7 +490,7 @@ export default class MiniMap extends Base {
self.set('container', container);
const containerDOM = createDOM(
const containerDOM = createDom(
'<div class="g6-minimap-container" style="position: relative;"></div>',
);
container.appendChild(containerDOM);

View File

@ -1,11 +1,10 @@
/**
* G
*/
import GCanvas from '@antv/g-canvas/lib/canvas';
import GSVGCanvas from '@antv/g-svg/lib/canvas';
import { IGroup, ICanvas } from '@antv/g-base';
import createDOM from '@antv/dom-util/lib/create-dom'
import modifyCSS from '@antv/dom-util/lib/modify-css'
import { Canvas as GCanvas } from '@antv/g-canvas';
import { Canvas as GSVGCanvas } from '@antv/g-svg';
import { ICanvas } from '@antv/g-base';
import { createDom, modifyCSS } from '@antv/dom-util';
import Base, { IPluginBaseConfig } from '../base';
import TrendTimeBar, { SliderOption } from './trendTimeBar'
import TimeBarSlice, { TimeBarSliceOption } from './timeBarSlice'
@ -116,7 +115,7 @@ export default class TimeBar extends Base {
let timeBarContainer;
if (!container) {
timeBarContainer = createDOM(`<div class='${className}'></div>`);
timeBarContainer = createDom(`<div class='${className}'></div>`);
modifyCSS(timeBarContainer, { position: 'relative' });
} else {
if (isString(container)) {

View File

@ -1,7 +1,7 @@
import * as pathUtil from '@antv/path-util';
import { Category, Linear } from '@antv/scale';
import { map, each, isEqual, head } from '@antv/util';
import isArray from '@antv/util/lib/is-array';
import { map, each, isEqual, head, isArray } from '@antv/util';
type Point = [number, number];

View File

@ -1,6 +1,5 @@
import createDOM from '@antv/dom-util/lib/create-dom'
import { isString } from '@antv/util';
import modifyCSS from '@antv/dom-util/lib/modify-css';
import { createDom, modifyCSS } from '@antv/dom-util';
export const BACKGROUND_STYLE = {
opacity: 0.5,
@ -108,7 +107,7 @@ export default class TimeBarTooltip {
textColor, text, padding, opacity, fontSize } = self;
let parentNode: string | HTMLElement = self.container;
const container: HTMLElement = createDOM(
const container: HTMLElement = createDom(
`<div class='${className}' style="position: absolute; width: fit-content; height: fit-content; opacity: ${opacity}"></div>`,
);
if (isString(parentNode)) {
@ -119,13 +118,13 @@ export default class TimeBarTooltip {
self.parentWidth = parentNode.offsetWidth;
modifyCSS(container, { visibility: 'hidden', top: 0, left: 0 });
const background: HTMLElement = createDOM(`
const background: HTMLElement = createDom(`
<div style='position: absolute; white-space:nowrap; background-color: ${backgroundColor}; font-size: ${fontSize}px; border-radius: 4px; width: fit-content; height: fit-content; color: ${textColor}; padding: ${padding[0]}px ${padding[1]}px ${padding[2]}px ${padding[3]}px'></div>`);
background.innerHTML = text;
container.appendChild(background);
self.backgroundDOM = background;
const arrow: HTMLElement = createDOM(
const arrow: HTMLElement = createDom(
`<div style='position: absolute; width: 0px; height: 0px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 10px solid ${backgroundColor}'></div>`
)
container.appendChild(arrow);
@ -157,7 +156,7 @@ export default class TimeBarTooltip {
modifyCSS(self.backgroundDOM, { marginLeft: `${-backgroundWidth / 2 - right + self.parentWidth + 12}px` })
}
}
public hide() {
modifyCSS(this.container as HTMLElement, { top: 0, left: 0, visibility: 'hidden', });
}

View File

@ -1,6 +1,5 @@
import modifyCSS from '@antv/dom-util/lib/modify-css';
import createDOM from '@antv/dom-util/lib/create-dom';
import { clone, isString } from '@antv/util/lib';
import { modifyCSS, createDom } from '@antv/dom-util';
import { clone, isString } from '@antv/util';
import Base, { IPluginBaseConfig } from '../base';
import { IGraph } from '../../interface/graph';
import { Point } from '@antv/g-base';
@ -94,7 +93,7 @@ export default class ToolBar extends Base {
const toolBar = getContent(graph);
let toolBarDOM = toolBar;
if (isString(toolBar)) {
toolBarDOM = createDOM(toolBar);
toolBarDOM = createDom(toolBar);
}
const className = this.get('className');

View File

@ -1,6 +1,5 @@
import modifyCSS from '@antv/dom-util/lib/modify-css';
import createDOM from '@antv/dom-util/lib/create-dom';
import isString from '@antv/util/lib/is-string';
import { modifyCSS, createDom } from '@antv/dom-util';
import { isString } from '@antv/util';
import insertCss from 'insert-css';
import Graph from '../../graph/graph';
import { IG6GraphEvent, Item } from '../../types';
@ -66,6 +65,9 @@ export default class Tooltip extends Base {
'edge:mouseenter': 'onMouseEnter',
'edge:mouseleave': 'onMouseLeave',
'edge:mousemove': 'onMouseMove',
'combo:mouseenter': 'onMouseEnter',
'combo:mouseleave': 'onMouseLeave',
'combo:mousemove': 'onMouseMove',
afterremoveitem: 'onMouseLeave',
'contextmenu': 'onMouseLeave',
'node:drag': 'onMouseLeave'
@ -74,7 +76,7 @@ export default class Tooltip extends Base {
public init() {
const className = this.get('className') || 'g6-component-tooltip';
const tooltip = createDOM(`<div class=${className}></div>`);
const tooltip = createDom(`<div class=${className}></div>`);
let container: HTMLDivElement | null = this.get('container');
if (!container) {
container = this.get('graph').get('container');

View File

@ -2,7 +2,7 @@
* @fileOverview common combo shape
* @author shiwu.wyy@antfin.com
*/
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { isArray, isNil, clone } from '@antv/util';
import { ILabelConfig, ShapeOptions } from '../interface/shape';

View File

@ -1,4 +1,4 @@
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { Item, ComboConfig, ShapeStyle } from '../../types';
import Global from '../../global';

View File

@ -1,4 +1,4 @@
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { mix, isNumber, clone, isNil } from '@antv/util';
import { LabelStyle, Item, ComboConfig, ShapeStyle } from '../../types';

View File

@ -5,9 +5,9 @@
*/
import { Point } from '@antv/g-base/lib/types';
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape, IElement } from '@antv/g-canvas/lib/interfaces';
import { deepMix, mix, each, isNil } from '@antv/util';
import { deepMix, mix, each, isNil, isNumber, isArray } from '@antv/util';
import { ILabelConfig, ShapeOptions } from '../interface/shape';
import { EdgeConfig, EdgeData, IPoint, LabelStyle, ShapeStyle, Item, ModelConfig } from '../types';
import { getLabelPosition, getLoopCfgs } from '../util/graphic';
@ -17,8 +17,6 @@ import Global from '../global';
import Shape from './shape';
import { shapeBase, CLS_LABEL_BG_SUFFIX } from './shapeBase';
import { Path } from '@antv/g-canvas/lib/shape';
import isArray from '@antv/util/lib/is-array';
import isNumber from '@antv/util/lib/is-number';
const CLS_SHAPE = 'edge-shape';
@ -147,22 +145,33 @@ const singleEdge: ShapeOptions = {
// 添加结束点
points.push(endPoint);
const previousStyle = mix({}, strokeStyle, shape.attr(), cfg.style);
const currentAttr = shape.attr();
const previousStyle = mix({}, strokeStyle, currentAttr, cfg.style);
const source = cfg.sourceNode;
const target = cfg.targetNode;
let routeCfg: { [key: string]: unknown } = { radius: previousStyle.radius };
if (!controlPoints) {
routeCfg = { source, target, offset: previousStyle.offset, radius: previousStyle.radius };
}
if (currentAttr.endArrow && previousStyle.endArrow === false) {
cfg.style.endArrow = {
path: ''
};
}
if (currentAttr.startArrow && previousStyle.startArrow === false) {
cfg.style.startArrow = {
path: ''
};
}
const path = (this as any).getPath(points, routeCfg);
const style = mix(
strokeStyle,
shape.attr(),
{
lineWidth: size,
path,
path
},
cfg.style,
cfg.style
);
if (shape) {

View File

@ -1,5 +1,5 @@
import { Point } from '@antv/g-base/lib/types';
import Group from '@antv/g-canvas/lib/group';
import { Group } from '@antv/g-canvas';
import { mix, each, isArray, isString } from '@antv/util';
import { ShapeStyle, EdgeConfig, Item } from '../../types';
import { pointsToPolygon } from '../../util/path';
@ -118,7 +118,8 @@ Shape.registerEdge(
// 添加结束点
points.push(endPoint);
const previousStyle = mix({}, strokeStyle, shape.attr(), cfg.style);
const currentAttr = shape.attr();
const previousStyle = mix({}, strokeStyle, currentAttr, cfg.style);
const source = cfg.sourceNode;
const target = cfg.targetNode;
const radius = previousStyle.radius;
@ -131,12 +132,22 @@ Shape.registerEdge(
if (isNaN(startPoint.x) || isNaN(startPoint.y) || isNaN(endPoint.x) || isNaN(endPoint.y)) {
path = 'M0 0, L0 0';
}
if (currentAttr.endArrow && previousStyle.endArrow === false) {
cfg.style.endArrow = {
path: ''
};
}
if (currentAttr.startArrow && previousStyle.startArrow === false) {
cfg.style.startArrow = {
path: ''
};
}
const style = mix(
strokeStyle,
shape.attr(),
{
lineWidth: size,
path,
path
},
cfg.style,
);

View File

@ -6,7 +6,7 @@
*/
import { INode } from '../../interface/item';
import { Item } from '../../types';
import deepMix from '@antv/util/lib/deep-mix';
import { deepMix } from '@antv/util';
import { getLineIntersect } from '../../util/math';
import {
getExpandedBBox,

View File

@ -2,7 +2,7 @@
* @fileOverview common node shape
* @author huangtonger@aliyun.com
*/
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape, IElement } from '@antv/g-canvas/lib/interfaces';
import { isArray, isNil, mix } from '@antv/util';
import { ILabelConfig, ShapeOptions } from '../interface/shape';

View File

@ -1,6 +1,6 @@
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import deepMix from '@antv/util/lib/deep-mix';
import { deepMix } from '@antv/util';
import { Item, NodeConfig, ShapeStyle } from '../../types';
import Global from '../../global';
import Shape from '../shape';

View File

@ -1,4 +1,4 @@
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { mix } from '@antv/util';
import { Item, NodeConfig, ShapeStyle } from '../../types';

View File

@ -1,4 +1,4 @@
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { mix } from '@antv/util';
import { Item, NodeConfig, ShapeStyle } from '../../types';

View File

@ -1,6 +1,6 @@
import Shape from '../shape';
import { NodeConfig, Item } from '../../types';
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
/**

View File

@ -1,4 +1,4 @@
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { mix, isString } from '@antv/util';
import { Item, NodeConfig, ShapeStyle } from '../../types';

View File

@ -1,4 +1,4 @@
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { mix } from '@antv/util';
import { Item, NodeConfig, ShapeStyle } from '../../types';

View File

@ -1,4 +1,4 @@
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { mix } from '@antv/util';
import { Item, NodeConfig, ShapeStyle } from '../../types';

View File

@ -1,7 +1,7 @@
import Shape from '../shape';
import { mix } from '@antv/util';
import Global from '../../global';
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { ModelConfig, NodeConfig, Item, ShapeStyle } from '../../types';
import { ShapeOptions } from '../../interface/shape';

View File

@ -3,7 +3,7 @@
* @author dxq613@gmail.com
*/
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape } from '@antv/g-canvas/lib/interfaces';
import { upperFirst } from '@antv/util';
import { ShapeOptions, ShapeDefine } from '../interface/shape';
@ -132,17 +132,17 @@ const ShapeFramework = {
/**
*
*/
drawShape(/* cfg, group */) {},
drawShape(/* cfg, group */) { },
/**
* 便
*/
afterDraw(/* cfg, group */) {},
afterDraw(/* cfg, group */) { },
// update(cfg, item) // 默认不定义
afterUpdate(/* cfg, item */) {},
afterUpdate(/* cfg, item */) { },
/**
*
*/
setState(/* name, value, item */) {},
setState(/* name, value, item */) { },
/**
*
* @param {Object} cfg

View File

@ -2,7 +2,7 @@
* @fileOverview
* @author dxq613@gmail.com
*/
import GGroup from '@antv/g-canvas/lib/group';
import { Group as GGroup } from '@antv/g-canvas';
import { IShape, IElement } from '@antv/g-canvas/lib/interfaces';
import { ShapeOptions, ILabelConfig } from '../interface/shape';
import { IPoint, Item, LabelStyle, ShapeStyle, ModelConfig, EdgeConfig } from '../types';
@ -339,23 +339,21 @@ export const shapeBase: ShapeOptions = {
const model = item.getModel();
// 原始样式
// const originStyle = clone(item.getOriginStyle());
const originStyle = mix({}, model.style, clone(item.getOriginStyle()));
const keyShapeName = shape.get('name');
const keyShapeStyles = shape.attr();
const keyShapeStyles = clone(shape.attr());
// 已有样式 - 要取消的状态的样式
const filtetDisableStatesStyle = {};
// style 为要取消的状态的样式
// styles 为要取消的状态的样式
for (const p in styles) {
const style = styles[p];
if (isPlainObject(style) && !ARROWS.includes(p)) {
const subShape = group.find((element) => element.get('name') === p);
if (subShape) {
const subShapeStyles = subShape.attr();
// const current = subShapeStyles[p]
each(style, (v, key) => {
if (subShapeStyles[key] || subShapeStyles[key] === 0) {
delete subShapeStyles[key];
@ -368,6 +366,7 @@ export const shapeBase: ShapeOptions = {
const keptAttrs = { x: 1, y: 1, cx: 1, cy: 1 };
if (keyShapeStyles[p] && !keptAttrs[p]) {
delete keyShapeStyles[p];
shape.attr(p, originStyle[p]);
}
}
}

View File

@ -3,7 +3,7 @@
* @author xuzhi.mxz@antfin.com
*/
import get from '@antv/util/lib/get';
import { get } from '@antv/util';
import { getTextSize } from '../util/graphic';
/**

View File

@ -1,13 +1,13 @@
/* eslint @typescript-eslint/no-use-before-define: 0 */
import GraphEvent from '@antv/g-base/lib/event/graph-event';
import { IGroup, Event as GraphEvent } from '@antv/g-base';
import { BBox, AnimateCfg } from '@antv/g-base/lib/types';
import Canvas from '@antv/g-canvas/lib/canvas';
import ShapeBase from '@antv/g-canvas/lib/shape/base';
import { Canvas, Shape } from '@antv/g-canvas';
import Node from '../item/node';
import { IGraph } from '../interface/graph';
import { IEdge, INode, ICombo } from '../interface/item';
import { ILabelConfig } from '../interface/shape';
import { IGroup } from '@antv/g-base';
type ShapeBase = Shape.Base;
// Node Edge Combo 实例
export type Item = INode | IEdge | ICombo;

View File

@ -1,7 +1,4 @@
import isArray from '@antv/util/lib/is-array';
import isNil from '@antv/util/lib/is-nil';
import isNumber from '@antv/util/lib/is-number';
import isString from '@antv/util/lib/is-string';
import { isString, isNumber, isNil, isArray } from '@antv/util';
import { G6GraphEvent } from '../interface/behavior';
import { IG6GraphEvent, Padding, Matrix, Item } from '../types';
@ -215,7 +212,7 @@ export const gpuDetector = (): any => {
if (typeof window === 'undefined' || typeof document === 'undefined') return {};
return {
canvas: !!window.CanvasRenderingContext2D,
webgl: (function () {
webgl: (() => {
try {
const canvas = document.createElement('canvas');
return !!(window.WebGLRenderingContext && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')));
@ -225,7 +222,7 @@ export const gpuDetector = (): any => {
})(),
workers: !!window.Worker,
fileapi: window.File && window.FileReader && window.FileList && window.Blob,
getWebGLErrorMessage: function () {
getWebGLErrorMessage: () => {
const element = document.createElement('div');
element.id = 'webgl-error-message';
element.style.fontFamily = 'monospace';
@ -248,7 +245,7 @@ export const gpuDetector = (): any => {
}
return element;
},
addGetWebGLMessage: function (parameters) {
addGetWebGLMessage(parameters) {
parameters = parameters || {};
const parent = parameters.parent !== undefined ? parameters.parent : document.body;
const id = parameters.id !== undefined ? parameters.id : 'oldie';

View File

@ -1,4 +1,4 @@
import Group from '@antv/g-canvas/lib/group';
import { Group } from '@antv/g-canvas';
import Path from '@antv/g-canvas/lib/shape/path';
import { vec2 } from '@antv/matrix-util';
import Global from '../global';

View File

@ -3,12 +3,8 @@ import * as GraphicUtil from './graphic';
import * as PathUtil from './path';
import * as BaseUtil from './base';
import * as ColorUtil from './color';
import { mat3, transform } from '@antv/matrix-util/lib';
import mix from '@antv/util/lib/mix';
import deepMix from '@antv/util/lib/deep-mix';
import isArray from '@antv/util/lib/is-array';
import isNumber from '@antv/util/lib/is-number';
import { uniqueId } from '@antv/util';
import { mat3, transform } from '@antv/matrix-util';
import { mix, isNumber, deepMix, isArray, uniqueId } from '@antv/util';
const Base = {
mat3,

View File

@ -1,7 +1,7 @@
import { Point } from '@antv/g-base/lib/types';
import { IGroup } from '@antv/g-canvas/lib/interfaces';
import { mat3, transform, vec3 } from '@antv/matrix-util';
import isArray from '@antv/util/lib/is-array';
import { isArray } from '@antv/util';
import {
GraphData,
ICircle,

View File

@ -2,480 +2,94 @@ import React, { useEffect } from 'react';
import G6, { Algorithm } from '../../../src';
const { findAllPath, findShortestPath } = Algorithm;
const data = {
nodes: [
{
id: '0',
label: '0',
},
{
id: '1',
label: '1',
},
{
id: '2',
label: '2',
},
{
id: '3',
label: '3',
},
{
id: '4',
label: '4',
},
{
id: '5',
label: '5',
},
{
id: '6',
label: '6',
},
{
id: '7',
label: '7',
},
{
id: '8',
label: '8',
},
{
id: '9',
label: '9',
},
{
id: '10',
label: '10',
},
{
id: '11',
label: '11',
},
{
id: '12',
label: '12',
},
{
id: '13',
label: '13',
},
{
id: '14',
label: '14',
},
{
id: '15',
label: '15',
},
{
id: '16',
label: '16',
},
{
id: '17',
label: '17',
},
{
id: '18',
label: '18',
},
{
id: '19',
label: '19',
},
{
id: '20',
label: '20',
},
{
id: '21',
label: '21',
},
{
id: '22',
label: '22',
},
{
id: '23',
label: '23',
},
{
id: '24',
label: '24',
},
{
id: '25',
label: '25',
},
{
id: '26',
label: '26',
},
{
id: '27',
label: '27',
},
{
id: '28',
label: '28',
},
{
id: '29',
label: '29',
},
{
id: '30',
label: '30',
},
{
id: '31',
label: '31',
},
{
id: '32',
label: '32',
},
{
id: '33',
label: '33',
},
],
edges: [
{
source: '0',
target: '1',
},
{
source: '0',
target: '2',
},
{
source: '0',
target: '3',
},
{
source: '0',
target: '4',
},
{
source: '0',
target: '5',
},
{
source: '0',
target: '7',
},
{
source: '0',
target: '8',
},
{
source: '0',
target: '9',
},
{
source: '0',
target: '10',
},
{
source: '0',
target: '11',
},
{
source: '0',
target: '13',
},
{
source: '0',
target: '14',
},
{
source: '0',
target: '15',
},
{
source: '0',
target: '16',
},
{
source: '2',
target: '3',
},
{
source: '4',
target: '5',
},
{
source: '4',
target: '6',
},
{
source: '5',
target: '6',
},
{
source: '7',
target: '13',
},
{
source: '8',
target: '14',
},
{
source: '9',
target: '10',
},
{
source: '10',
target: '22',
},
{
source: '10',
target: '14',
},
{
source: '10',
target: '12',
},
{
source: '10',
target: '24',
},
{
source: '10',
target: '21',
},
{
source: '10',
target: '20',
},
{
source: '11',
target: '24',
},
{
source: '11',
target: '22',
},
{
source: '11',
target: '14',
},
{
source: '12',
target: '13',
},
{
source: '16',
target: '17',
},
{
source: '16',
target: '18',
},
{
source: '16',
target: '21',
},
{
source: '16',
target: '22',
},
{
source: '17',
target: '18',
},
{
source: '17',
target: '20',
},
{
source: '18',
target: '19',
},
{
source: '19',
target: '20',
},
{
source: '19',
target: '33',
},
{
source: '19',
target: '22',
},
{
source: '19',
target: '23',
},
{
source: '20',
target: '21',
},
{
source: '21',
target: '22',
},
{
source: '22',
target: '24',
},
{
source: '22',
target: '25',
},
{
source: '22',
target: '26',
},
{
source: '22',
target: '23',
},
{
source: '22',
target: '28',
},
{
source: '22',
target: '30',
},
{
source: '22',
target: '31',
},
{
source: '22',
target: '32',
},
{
source: '22',
target: '33',
},
{
source: '23',
target: '28',
},
{
source: '23',
target: '27',
},
{
source: '23',
target: '29',
},
{
source: '23',
target: '30',
},
{
source: '23',
target: '31',
},
{
source: '23',
target: '33',
},
{
source: '32',
target: '33',
},
],
};
const FindPath = () => {
const container = React.useRef();
useEffect(() => {
let sourceNode, targetNode, operation;
const contextMenu = new G6.Menu({
getContent(graph) {
console.log('graph', graph);
return `<div>
<div title='all'></div>
<div title='short'></div>
</div>`;
},
handleMenuClick: (target, item) => {
operation = target.title;
sourceNode = item;
},
offsetX: 0,
offsetY: 0,
itemTypes: ['node', 'edge'],
});
const div = document.getElementById('container');
const tipDiv = document.createElement('div');
tipDiv.innerHTML = `Press 'shift' and click two nodes to select begin and end nodes. 按住 'shift' 并点选两个节点作为起点和终点。`;
const button = document.createElement('button');
button.innerHTML = `查看最短路径`;
div.appendChild(tipDiv);
div.appendChild(button);
const graph = new G6.Graph({
container: container.current,
container: container?.current,
width: 500,
height: 500,
plugins: [contextMenu],
defaultEdge: {
style: {
endArrow: true,
},
},
edgeStateStyles: {
isPath: {
stroke: 'orange',
strokeOpacity: 0.4,
lineWidth: 3,
},
highlight: {
stroke: 'lightgreen',
strokeOpacity: 0.6,
lineWidth: 4,
},
},
linkCenter: true,
modes: {
default: ['zoom-canvas', 'drag-canvas', 'drag-node'],
default: ['click-select', 'drag-canvas', 'drag-node', 'zoom-canvas'],
},
});
graph.data(data);
graph.render();
graph.on('node:click', (e) => {
graph.getEdges().forEach((edge) => {
graph.clearItemStates(edge);
});
if (sourceNode && operation === 'all') {
targetNode = e.item;
const allPaths = findAllPath(graph, sourceNode, targetNode, true);
allPaths.forEach((path) => {
for (let i = 0; i < path.length - 1; i++) {
const start = path[i];
const end = path[i + 1];
graph.getEdges().forEach((edge) => {
if (edge.getSource().get('id') === start && edge.getTarget().get('id') === end) {
graph.setItemState(edge, 'isPath', true);
}
});
}
});
sourceNode = null;
targetNode = null;
fitView: true,
layout: {
type: 'force'
}
if (sourceNode && operation === 'short') {
targetNode = e.item;
const { length, path } = findShortestPath(graph, sourceNode, targetNode, true);
for (let i = 0; i < path.length - 1; i++) {
const start = path[i];
const end = path[i + 1];
graph.getEdges().forEach((edge) => {
if (edge.getSource().get('id') === start && edge.getTarget().get('id') === end) {
graph.setItemState(edge, 'highlight', true);
}
});
fetch('https://gw.alipayobjects.com/os/bmw-prod/b0ca4b15-bd0c-43ec-ae41-c810374a1d55.json')
.then((res) => res.json())
.then((data) => {
const clearStates = () => {
graph.getNodes().forEach(node => {
graph.clearItemStates(node);
});
graph.getEdges().forEach(edge => {
graph.clearItemStates(edge);
});
}
sourceNode = null;
targetNode = null;
}
});
graph.on('canvas:click', e => {
clearStates();
});
graph.data(data);
graph.render();
button.addEventListener('click', e => {
const selectedNodes = graph.findAllByState('node', 'selected');
if (selectedNodes.length !== 2) {
alert('Please select TWO nodes!\n\r请选择有且两个节点');
return;
}
clearStates();
const { findShortestPath } = G6.Algorithm;
const { path } = findShortestPath(graph, selectedNodes[0].getID(), selectedNodes[1].getID());
const pathNodeMap = {};
path.forEach(id => {
const pathNode = graph.findById(id);
pathNode.toFront();
graph.setItemState(pathNode, 'highlight', true);
pathNodeMap[id] = true;
});
graph.getEdges().forEach(edge => {
const edgeModel = edge.getModel();
const source = edgeModel.source;
const target = edgeModel.target;
const sourceInPathIdx = path.indexOf(source);
const targetInPathIdx = path.indexOf(target);
if (sourceInPathIdx === -1 || targetInPathIdx === -1) return;
if (Math.abs(sourceInPathIdx - targetInPathIdx) === 1) {
graph.setItemState(edge, 'highlight', true);
} else {
graph.setItemState(edge, 'inactive', true);
}
});
graph.getNodes().forEach(node => {
if (!pathNodeMap[node.getID()]) {
graph.setItemState(node, 'inactive', true);
}
});
});
});
});
return <div ref={container}></div>;
return <div ref={container} id='container'></div>;
};
export default FindPath;

View File

@ -415,7 +415,7 @@ G6.registerNode('real-node', {
}, 'aggregated-node'); // 这样可以继承 aggregated-node 的 setState
// Custom the quadratic edge for multiple edges between one node pair
G6.registerEdge('quadratic', {
G6.registerEdge('custom-quadratic', {
setState: (name, value, item) => {
const group = item.get('group');
const model = item.getModel();
@ -511,7 +511,7 @@ G6.registerEdge('quadratic', {
}, 'quadratic');
// Custom the line edge for single edge between one node pair
G6.registerEdge('line', {
G6.registerEdge('custom-line', {
setState: (name, value, item) => {
const group = item.get('group');
const model = item.getModel();
@ -847,7 +847,7 @@ const processNodesEdges = (nodes, edges, width, height, largeGraphMode, edgeLabe
}
});
G6.Util.processParallelEdges(edges, 12.5, 'quadratic', 'line');
G6.Util.processParallelEdges(edges, 12.5, 'custom-quadratic', 'custom-line');
return {
maxDegree,
edges
@ -1473,7 +1473,7 @@ const LargeGraph = () => {
cedge.loopCfg = {
dist: 20,
}
} else cedge.type = 'line';
} else cedge.type = 'custom-line';
aggregatedData.edges.push(cedge);
});
@ -1609,7 +1609,7 @@ const LargeGraph = () => {
size: DEFAULTNODESIZE,
},
plugins: [contextMenu],
layout: layoutConfig
layout: layoutConfig,
});
graph.get('canvas').set('localRefresh', false);

View File

@ -241,13 +241,24 @@ const RegisterLayout = () => {
defaultEdge: {
size: 1,
color: '#e2e2e2',
type: 'line'
},
modes: {
default: ['drag-canvas', 'drag-node'],
},
}
});
graph.data(data);
graph.render();
graph.on('edge:mouseenter', (e) => {
console.log('enter')
debugger
graph.setItemState(e.item, 'active', true);
});
graph.on('edge:mouseout', (e) => {
graph.setItemState(e.item, 'active', false);
});
}
});

View File

@ -11,18 +11,20 @@ const data = {
x: 150,
y: 50,
label: 'node1',
comboId: 'a'
},
{
id: 'node2',
x: 200,
x: 500,
y: 150,
label: 'node2',
label: 'node2'
},
{
id: 'node3',
x: 100,
y: 150,
label: 'node3',
comboId: 'a'
},
],
edges: [
@ -39,6 +41,11 @@ const data = {
target: 'node1',
},
],
combos: [
{
id: 'a'
}
]
};
const Tooltip = () => {
@ -48,14 +55,14 @@ const Tooltip = () => {
const tooltip = new G6.Tooltip({
offsetX: 100,
offsetY: 120, // the height of the top div
shouldBegin: d => {
if (d.target.get('name') === 'text-shape') return true;
return false;
},
// shouldBegin: d => {
// if (d.target.get('name') === 'text-shape') return true;
// return false;
// },
getContent: e => {
return e.target.get('name') || e.target.get('className') || 'aaa';
},
itemTypes: ['node']
itemTypes: ['node', 'combo']
});
graph = new Graph({
container: container.current as string | HTMLElement,

View File

@ -32,10 +32,20 @@ const data = {
type: 'polyline',
curveOffset: -150,
curvePosition: 0.5,
style: {
endArrow: {
path: G6.Arrow.triangle(5, 15, 0)
}
}
},
{
source: '1',
target: '3',
style: {
endArrow: {
path: G6.Arrow.triangle(5, 15, 0)
}
}
},
],
};
@ -69,6 +79,32 @@ const Quadratic = () => {
});
graph.data(data);
graph.render();
graph.on('canvas:click', e => {
const edge = graph.getEdges()[0];
const keyShape = edge.getKeyShape();
// keyShape.attr('endArrow', { path: '' });
// keyShape.attr('stroke', '#f00');
graph.updateItem(graph.getEdges()[1], {
style: {
endArrow: false,
stroke: '#f00'
},
});
// console.log(graph.getEdges()[0])
});
graph.on('edge:click', e => {
graph.updateItem(graph.getEdges()[1], {
style: {
endArrow: {
path: G6.Arrow.triangle(15, 15, 0)
},
stroke: '#0f0'
},
});
});
}
});

View File

@ -30,38 +30,24 @@ const TreeData = () => {
height: 800,
modes: {
default: [
{
type: 'collapse-expand',
onChange: function onChange(item, collapsed) {
const data = item.get('model').data;
data.collapsed = collapsed;
return true;
},
},
'drag-canvas',
'zoom-canvas',
'drag-node'
],
},
defaultNode: {
size: 26,
anchorPoints: [
[0, 0.5],
[1, 0.5],
],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
// defaultNode: {
// type: 'circle'
// },
defaultEdge: {
type: 'cubic-horizontal',
type: 'line',
style: {
stroke: '#A3B1BF',
},
lineAppendWidth: 5
}
},
nodeStateStyles: {
selected: {
fill: 'red'
active: {
fillOpacity: 0.1,
shadowBlur: 0
}
},
layout: {
@ -85,42 +71,64 @@ const TreeData = () => {
},
});
graph.node(function (node) {
return {
label: node.id,
labelCfg: {
offset: 10,
position: node.children && node.children.length > 0 ? 'left' : 'right',
},
};
});
// graph.node(function (node) {
// return {
// label: node.id,
// labelCfg: {
// offset: 10,
// position: node.children && node.children.length > 0 ? 'left' : 'right',
// },
// };
// });
graph.data(data);
graph.render();
graph.fitView();
graph.on('node:mouseenter', (e) => {
graph.setItemState(e.item, 'hover', true);
console.log(e.item);
graph.setItemState(e.item, 'active', true);
});
graph.on('node:mouseout', (e) => {
graph.setItemState(e.item, 'active', false);
});
graph.setItemState(graph.getNodes()[10], 'selected', true);
graph.on("node:click", (evt) => {
console.log('clicking')
const { item } = evt;
const nodes = graph.findAllByState("node", "selected");
debugger
nodes.forEach((node) => graph.setItemState(node, "selected", false));
graph.setItemState(item, "selected", true);
const nodeData = graph.findDataById(item.getID());
const node = {
id: `${Math.floor(Math.random() * 1000)}`,
label: "test" + Math.random() * 1000
};
if (!nodeData.children) {
nodeData.children = [node];
} else {
nodeData.children.push(node);
}
graph.changeData();
// graph.clearItemStates(graph.getNodes()[10]);
graph.getNodes().forEach(node => {
graph.clearItemStates(node);
});
graph.setItemState(item, 'selected', true);
});
graph.on('edge:mouseenter', (e) => {
console.log('enter')
graph.setItemState(e.item, 'active', true);
});
graph.on('edge:mouseout', (e) => {
graph.setItemState(e.item, 'active', false);
console.log(e.item)
});
graph.on("edge:click", (evt) => {
console.log('clicking')
const { item } = evt;
// graph.clearItemStates(graph.getNodes()[10]);
graph.getEdges().forEach(edge => {
graph.clearItemStates(edge);
});
graph.setItemState(item, 'selected', true);
});
graph.on('canvas:click', e => {
graph.getEdges().forEach(edge => {
// graph.clearItemStates(edge);
graph.setItemState(edge, 'selected', false);
});
});
});
}

View File

@ -94,7 +94,7 @@ describe('graph', () => {
const children = inst.get('group').get('children');
expect(children.length).toBe(4);
expect(children[1].get('className')).toEqual('edge-container');
const nodes = inst.getNodes();
expect(nodes).not.toBe(undefined);
expect(nodes.length).toBe(0);
@ -1237,7 +1237,7 @@ describe('behaviors', () => {
expect(itemKeyShape.attr('lineWidth')).toBe(1);
expect(unrelativeNodeKeyShape.attr('lineWidth')).toBe(1);
expect(unrelativeNodeKeyShape.attr('stroke')).toBe('rgb(95, 149, 255)');
expect(unrelativeNodeKeyShape.attr('opacity')).toBe(1);
expect(unrelativeNodeKeyShape.attr('opacity')).toBe(undefined);
});
it('click-select', () => {
graph.setMode('select');

View File

@ -181,7 +181,7 @@ describe('combo node test', () => {
factory.setState('rectnode', 'active', true, item);
expect(shape.attr('fillOpacity')).not.toBe(1);
factory.setState('rectnode', 'active', false, item);
expect(shape.attr('fillOpacity')).toBe(1);
expect(shape.attr('fillOpacity')).toBe(undefined);
});
it('label position', () => {

View File

@ -238,7 +238,7 @@ describe('shape node test', () => {
factory.setState('rectnode', 'active', true, item);
expect(shape.attr('fillOpacity')).not.toBe(1);
factory.setState('rectnode', 'active', false, item);
expect(shape.attr('fillOpacity')).toBe(1);
expect(shape.attr('fillOpacity')).toBe(undefined);
});
it('selected', () => {

View File

@ -75,7 +75,7 @@ describe('graph edge states', () => {
graph.setItemState(item, 'hover', false);
expect(item.hasState('hover')).toEqual(false);
const keyShape = item.getKeyShape();
expect(keyShape.attr('opacity')).toEqual(1);
expect(keyShape.attr('opacity')).toEqual(undefined);
expect(keyShape.attr('lineWidth')).toEqual(3);
expect(keyShape.attr('stroke')).toEqual('steelblue');
});

View File

@ -172,7 +172,7 @@ describe('graph refactor states', () => {
expect(item.hasState('select')).toBe(false);
expect(item.getStates()).toEqual(['hover']);
expect(keyShape.attr('lineWidth')).toBe(1);
expect(keyShape.attr('stroke')).toBe(undefined);
expect(keyShape.attr('stroke')).toBe('rgb(95, 149, 255)');
// remove hover states
graph.setItemState(item, 'hover', false);