StructV2/src/engine.ts
2021-12-09 16:59:44 +08:00

231 lines
6.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Sources } from "./sources";
import { ModelConstructor } from "./Model/modelConstructor";
import { AnimationOptions, EngineOptions, InteractionOptions, LayoutGroupOptions, ViewOptions } from "./options";
import { SV } from "./StructV";
import { EventBus } from "./Common/eventBus";
import { ViewContainer } from "./View/viewContainer";
import { SVLink } from "./Model/SVLink";
import { SVNode } from "./Model/SVNode";
import { SVMarker } from "./Model/SVMarker";
export class Engine {
private modelConstructor: ModelConstructor;
private viewContainer: ViewContainer
private prevStringSourceData: string;
public engineOptions: EngineOptions;
public viewOptions: ViewOptions;
public animationOptions: AnimationOptions;
public interactionOptions: InteractionOptions;
public optionsTable: { [key: string]: LayoutGroupOptions };
constructor(DOMContainer: HTMLElement, engineOptions: EngineOptions) {
this.optionsTable = {};
this.engineOptions = Object.assign({}, engineOptions);
this.viewOptions = Object.assign({
fitCenter: true,
fitView: false,
groupPadding: 20,
leakAreaHeight: 150,
updateHighlight: '#fc5185'
}, engineOptions.view);
this.animationOptions = Object.assign({
enable: true,
duration: 750,
timingFunction: 'easePolyOut'
}, engineOptions.animation);
this.interactionOptions = Object.assign({
drag: true,
zoom: true,
dragNode: true,
selectNode: true
}, engineOptions.interaction);
// 初始化布局器配置项
Object.keys(SV.registeredLayout).forEach(layout => {
if(this.optionsTable[layout] === undefined) {
const options: LayoutGroupOptions = SV.registeredLayout[layout].defineOptions();
this.optionsTable[layout] = options;
}
});
this.modelConstructor = new ModelConstructor(this);
this.viewContainer = new ViewContainer(this, DOMContainer);
}
/**
* 输入数据进行渲染
* @param sourcesData
*/
public render(sourceData: Sources) {
if(sourceData === undefined || sourceData === null) {
return;
}
let stringSourceData = JSON.stringify(sourceData);
if(this.prevStringSourceData === stringSourceData) {
return;
}
this.prevStringSourceData = stringSourceData;
// 1 转换模型data => model
const layoutGroupTable = this.modelConstructor.construct(sourceData);
// 2 渲染使用g6进行渲染
this.viewContainer.render(layoutGroupTable);
}
/**
* 重新布局
*/
public reLayout() {
this.viewContainer.reLayout();
}
/**
* 获取 G6 实例
*/
public getGraphInstance() {
return this.viewContainer.getG6Instance();
}
/**
* 获取所有 element
* @param group
*/
public getNodes(group?: string): SVNode[] {
const layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
if(group && layoutGroupTable.has('group')) {
return layoutGroupTable.get('group').node;
}
const nodes: SVNode[] = [];
layoutGroupTable.forEach(item => {
nodes.push(...item.node);
})
return nodes;
}
/**
* 获取所有 marker
* @param group
*/
public getMarkers(group?: string): SVMarker[] {
const layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
if(group && layoutGroupTable.has('group')) {
return layoutGroupTable.get('group').marker;
}
const markers: SVMarker[] = [];
layoutGroupTable.forEach(item => {
markers.push(...item.marker);
})
return markers;
}
/**
* 获取所有 link
* @param group
*/
public getLinks(group?: string): SVLink[] {
const layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
if(group && layoutGroupTable.has('group')) {
return layoutGroupTable.get('group').link;
}
const links: SVLink[] = [];
layoutGroupTable.forEach(item => {
links.push(...item.link);
})
return links;
}
/**
* 隐藏某些组
* @param groupNames
*/
public hideGroups(groupNames: string | string[]) {
const names = Array.isArray(groupNames)? groupNames: [groupNames],
instance = this.viewContainer.getG6Instance(),
layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
layoutGroupTable.forEach(item => {
const hasName = names.find(name => name === item.layout);
if(hasName && !item.isHide) {
item.modelList.forEach(model => instance.hideItem(model.G6Item));
item.isHide = true;
}
if(!hasName && item.isHide) {
item.modelList.forEach(model => instance.showItem(model.G6Item));
item.isHide = false;
}
});
}
/**
* 使用id查找某个节点
* @param id
*/
public findNode(id: string): SVNode {
const nodes = this.getNodes();
const stringId = id.toString();
const targetNode = nodes.find(item => item.sourceId === stringId);
return targetNode;
}
/**
* 调整容器尺寸
* @param width
* @param height
*/
public resize(width: number, height: number) {
this.viewContainer.resize(width, height);
}
/**
* 绑定 G6 事件
* @param eventName
* @param callback
*/
public on(eventName: string, callback: Function) {
if(typeof callback !== 'function') {
return;
}
if(eventName === 'onFreed' || eventName === 'onLeak') {
EventBus.on(eventName, callback);
return;
}
if(eventName === 'onLeakAreaUpdate') {
EventBus.on(eventName, callback);
return;
}
this.viewContainer.getG6Instance().on(eventName, event => {
callback(event.item['SVModel']);
});
}
/**
* 销毁引擎
*/
public destroy() {
this.modelConstructor.destroy();
this.viewContainer.destroy();
}
};