fix: 添加力导向布局
This commit is contained in:
parent
2cdc35ff30
commit
1f9ddfc672
71
demoV2/Layouter/Force.js
Normal file
71
demoV2/Layouter/Force.js
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
|
||||
|
||||
SV.registerLayout('Force', {
|
||||
defineOptions() {
|
||||
return {
|
||||
node: {
|
||||
default: {
|
||||
type: 'force-node',
|
||||
label: '[data]',
|
||||
size: 20,
|
||||
labelOptions: {
|
||||
style: { fontSize: 20 }
|
||||
},
|
||||
style: {
|
||||
stroke: 'red',
|
||||
fill: 'red'
|
||||
}
|
||||
}
|
||||
},
|
||||
link: {
|
||||
next: {
|
||||
type: 'line',
|
||||
sourceAnchor: 0,
|
||||
targetAnchor: 0,
|
||||
style: {
|
||||
stroke: '#333',
|
||||
lineAppendWidth: 6,
|
||||
cursor: 'pointer',
|
||||
// endArrow: 'default',
|
||||
startArrow: {
|
||||
path: G6.Arrow.circle(2, -1),
|
||||
fill: '#333'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
marker: {
|
||||
headExternal: {
|
||||
type: 'pointer',
|
||||
anchor: 3,
|
||||
style: {
|
||||
fill: '#f08a5d'
|
||||
}
|
||||
},
|
||||
external: {
|
||||
type: 'pointer',
|
||||
anchor: 0,
|
||||
style: {
|
||||
fill: '#f08a5d'
|
||||
}
|
||||
}
|
||||
},
|
||||
indexLabel: {
|
||||
index: { position: 'bottom' },
|
||||
indexRight: { position: 'right' }
|
||||
},
|
||||
behavior: {
|
||||
dragNode: true
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
layout(e) {
|
||||
console.log("here is the layout of Force")
|
||||
// e.forEach((item, index) => {
|
||||
// console.log(item.getBound());
|
||||
// })
|
||||
}
|
||||
});
|
||||
|
@ -2,7 +2,7 @@ import { Util } from "../Common/util";
|
||||
import { Style } from "../options";
|
||||
import { BoundingRect } from "../Common/boundingRect";
|
||||
import { EdgeConfig, Item, NodeConfig } from "@antv/g6-core";
|
||||
import { Graph } from "_@antv_g6-pc@0.5.0@@antv/g6-pc";
|
||||
import { Graph } from "@antv/g6";
|
||||
import merge from 'merge';
|
||||
|
||||
|
||||
|
47
src/RegisteredShape/force.ts
Normal file
47
src/RegisteredShape/force.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { Util } from "../Common/util";
|
||||
|
||||
|
||||
export default Util.registerShape('force-node', {
|
||||
draw(cfg, group) {
|
||||
// cfg.size = cfg.size;
|
||||
const size = 15;
|
||||
|
||||
const wrapperRect = group.addShape('circle', {
|
||||
attrs: {
|
||||
r: size,
|
||||
stroke: 'rgb(35, 120, 180)',
|
||||
// cursor: cfg.style.cursor,
|
||||
fill: 'rgb(31, 119, 180)'
|
||||
},
|
||||
name: 'wrapper'
|
||||
});
|
||||
|
||||
if (cfg.label) {
|
||||
const style = (cfg.labelCfg && cfg.labelCfg.style) || {};
|
||||
group.addShape('text', {
|
||||
attrs: {
|
||||
x: 0, // 居中
|
||||
y: 0,
|
||||
textAlign: 'center',
|
||||
textBaseline: 'middle',
|
||||
text: cfg.label,
|
||||
fill: style.fill || '#000',
|
||||
fontSize: style.fontSize || 10,
|
||||
cursor: cfg.style.cursor
|
||||
},
|
||||
name: 'text',
|
||||
draggable: true
|
||||
});
|
||||
}
|
||||
|
||||
return wrapperRect;
|
||||
},
|
||||
|
||||
getAnchorPoints() {
|
||||
return [
|
||||
[0.5, 0.5],
|
||||
[0, 0.5],
|
||||
[1, 0]
|
||||
];
|
||||
}
|
||||
}, 'rect');
|
@ -5,6 +5,7 @@ import G6 from '@antv/g6';
|
||||
import Pointer from "./RegisteredShape/pointer";
|
||||
import LinkListNode from "./RegisteredShape/linkListNode";
|
||||
import BinaryTreeNode from "./RegisteredShape/binaryTreeNode";
|
||||
import ForceNode from "./RegisteredShape/force";
|
||||
import CLenQueuePointer from "./RegisteredShape/clenQueuePointer";
|
||||
import TwoCellNode from "./RegisteredShape/twoCellNode";
|
||||
import ArrayNode from "./RegisteredShape/arrayNode";
|
||||
@ -20,7 +21,7 @@ import { SVNode } from "./Model/SVNode";
|
||||
|
||||
|
||||
export interface StructV {
|
||||
(DOMContainer: HTMLElement, engineOptions: EngineOptions): Engine;
|
||||
(DOMContainer: HTMLElement, engineOptions: EngineOptions, isForce: boolean): Engine;
|
||||
Group: typeof Group;
|
||||
Bound: typeof Bound;
|
||||
Vector: typeof Vector,
|
||||
@ -42,8 +43,8 @@ export interface StructV {
|
||||
}
|
||||
|
||||
|
||||
export const SV: StructV = function(DOMContainer: HTMLElement, engineOptions: EngineOptions = { }) {
|
||||
return new Engine(DOMContainer, engineOptions);
|
||||
export const SV: StructV = function(DOMContainer: HTMLElement, engineOptions: EngineOptions = { }, isForce: boolean) {
|
||||
return new Engine(DOMContainer, engineOptions, isForce);
|
||||
}
|
||||
|
||||
SV.Group = Group;
|
||||
@ -61,6 +62,7 @@ SV.registeredShape = [
|
||||
Cursor,
|
||||
ArrayNode,
|
||||
CLenQueuePointer,
|
||||
ForceNode
|
||||
];
|
||||
|
||||
SV.registerShape = Util.registerShape;
|
||||
|
@ -20,7 +20,7 @@ export class Renderer {
|
||||
private g6Instance: Graph; // g6 实例
|
||||
private shadowG6Instance: Graph;
|
||||
|
||||
constructor(engine: Engine, DOMContainer: HTMLElement, behaviorsModes: Modes) {
|
||||
constructor(engine: Engine, DOMContainer: HTMLElement, behaviorsModes: Modes, isForce: boolean) {
|
||||
this.engine = engine;
|
||||
|
||||
const enable: boolean = this.engine.animationOptions.enable,
|
||||
@ -41,6 +41,19 @@ export class Renderer {
|
||||
container: DOMContainer.cloneNode() as HTMLElement
|
||||
});
|
||||
|
||||
const forceOption = {
|
||||
type: 'force',
|
||||
linkDistance: 100, // 边长
|
||||
preventOverlap: true, // boolean,防止节点重叠
|
||||
// alphaDecay: 0, // 迭代阈值的衰减率。范围 [0, 1]。默认值0.028
|
||||
workEnabled: true, // 启用以防布局计算时间过长阻塞页面交互
|
||||
nodeStrength: -1, // 节点作用力,正数标识引力,负数表示斥力
|
||||
nodeSpacing: (d) => { // 设置了防止重叠后,节点边缘间距的最小值
|
||||
return 20;
|
||||
},
|
||||
center: [DOMContainer.offsetWidth / 2, DOMContainer.offsetHeight / 3],
|
||||
};
|
||||
const layout = isForce ? forceOption : null;
|
||||
// 初始化g6实例
|
||||
this.g6Instance = new Graph({
|
||||
container: DOMContainer,
|
||||
@ -52,10 +65,32 @@ export class Renderer {
|
||||
duration: duration,
|
||||
easing: timingFunction
|
||||
},
|
||||
fitView: false,
|
||||
modes: behaviorsModes,
|
||||
plugins: [tooltip]
|
||||
plugins: [tooltip],
|
||||
layout,
|
||||
});
|
||||
/**
|
||||
* 固定被拖拽节点
|
||||
*/
|
||||
function refreshDragedNodePosition(e) {
|
||||
const model = e.item.get('model');
|
||||
model.fx = e.x;
|
||||
model.fy = e.y;
|
||||
}
|
||||
this.g6Instance.on('node:dragstart', (e) => {
|
||||
this.g6Instance.layout();
|
||||
refreshDragedNodePosition(e);
|
||||
});
|
||||
this.g6Instance.on('node:drag', (e) => {
|
||||
refreshDragedNodePosition(e);
|
||||
});
|
||||
if (typeof window !== 'undefined') {
|
||||
window.onresize = () => {
|
||||
if (!this.g6Instance || this.g6Instance.get('destroyed')) return;
|
||||
if (!DOMContainer || !DOMContainer.scrollWidth || !DOMContainer.scrollHeight) return;
|
||||
this.g6Instance.changeSize(DOMContainer.scrollWidth, DOMContainer.scrollHeight);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,12 +30,12 @@ export class ViewContainer {
|
||||
public clickSelectNode: SVNode; // 点击选中的节点
|
||||
|
||||
|
||||
constructor(engine: Engine, DOMContainer: HTMLElement) {
|
||||
constructor(engine: Engine, DOMContainer: HTMLElement, isForce: boolean) {
|
||||
const behaviorsModes: Modes = InitG6Behaviors(engine, this);
|
||||
|
||||
this.engine = engine;
|
||||
this.layoutProvider = new LayoutProvider(engine, this);
|
||||
this.renderer = new Renderer(engine, DOMContainer, behaviorsModes);
|
||||
this.renderer = new Renderer(engine, DOMContainer, behaviorsModes, isForce);
|
||||
this.reconcile = new Reconcile(engine, this.renderer);
|
||||
this.layoutGroupTable = new Map();
|
||||
this.prevModelList = [];
|
||||
|
@ -18,7 +18,7 @@ export class Engine {
|
||||
public animationOptions: AnimationOptions;
|
||||
public behaviorOptions: BehaviorOptions;
|
||||
|
||||
constructor(DOMContainer: HTMLElement, engineOptions: EngineOptions) {
|
||||
constructor(DOMContainer: HTMLElement, engineOptions: EngineOptions, isForce: boolean) {
|
||||
this.engineOptions = Object.assign({}, engineOptions);
|
||||
|
||||
this.viewOptions = Object.assign({
|
||||
@ -43,7 +43,7 @@ export class Engine {
|
||||
}, engineOptions.behavior);
|
||||
|
||||
this.modelConstructor = new ModelConstructor(this);
|
||||
this.viewContainer = new ViewContainer(this, DOMContainer);
|
||||
this.viewContainer = new ViewContainer(this, DOMContainer, isForce);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,13 +51,13 @@ export class Engine {
|
||||
* @param sources
|
||||
* @param force
|
||||
*/
|
||||
public render(source: Sources, force: boolean = false) {
|
||||
public render(source: Sources) {
|
||||
if (source === undefined || source === null) {
|
||||
return;
|
||||
}
|
||||
``
|
||||
let stringSource = JSON.stringify(source);
|
||||
if (force === false && this.prevStringSource === stringSource) {
|
||||
if (this.prevStringSource === stringSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user