StructV2/src/engine.ts
廖威敬 7b9fffe0ab Merge branch 'main' of https://gitlab.com/phenomLi/StructV2 into main
# Conflicts:
#	demo/Layouter/Force.js
#	src/Model/SVModel.ts
#	src/StructV.ts
#	src/View/renderer.ts
#	src/View/viewContainer.ts
#	src/engine.ts
2022-04-06 11:33:48 +08:00

239 lines
6.9 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 { handleUpdate, Sources } from "./sources";
import { LayoutGroupTable, ModelConstructor } from "./Model/modelConstructor";
import { AnimationOptions, BehaviorOptions, EngineOptions, LayoutGroupOptions, ViewOptions } from "./options";
import { EventBus } from "./Common/eventBus";
import { ViewContainer } from "./View/viewContainer";
import { SVNode } from "./Model/SVNode";
import { Util } from "./Common/util";
import { SVModel } from "./Model/SVModel";
import { G6Event } from "@antv/g6";
export class Engine {
private modelConstructor: ModelConstructor;
private viewContainer: ViewContainer;
private prevStringSource: string;
public engineOptions: EngineOptions;
public viewOptions: ViewOptions;
public animationOptions: AnimationOptions;
public behaviorOptions: BehaviorOptions;
constructor(DOMContainer: HTMLElement, engineOptions: EngineOptions, isForce: boolean) {
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.behaviorOptions = Object.assign({
drag: true,
zoom: true,
dragNode: true,
selectNode: true
}, engineOptions.behavior);
this.modelConstructor = new ModelConstructor(this);
this.viewContainer = new ViewContainer(this, DOMContainer, isForce);
}
/**
* 输入数据进行渲染
* @param sources
* @param prevStep
*/
public render(source: Sources) {
<<<<<<< HEAD
if (source === undefined || source === null) {
return;
}
``
let stringSource = JSON.stringify(source);
if (this.prevStringSource === stringSource) {
return;
=======
let isSameSources: boolean = false,
layoutGroupTable: LayoutGroupTable;
if (source === undefined || source === null) {
return;
}
let handleUpdate: handleUpdate = source.handleUpdate,
stringSource = JSON.stringify(source);
if (this.prevStringSource === stringSource) {
isSameSources = true;
>>>>>>> eac9d007bcc1b52fe573ddf6cb97030c9b2d3a6d
}
this.prevStringSource = stringSource;
if(isSameSources) {
// 若源数据两次一样的用回上一次的layoutGroupTable
layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
}
else {
// 1 转换模型data => model
layoutGroupTable = this.modelConstructor.construct(source);
}
// 2 渲染使用g6进行渲染
this.viewContainer.render(layoutGroupTable, isSameSources, handleUpdate);
}
/**
* 重新布局
*/
public reLayout() {
this.viewContainer.reLayout();
}
/**
* 获取 G6 实例
*/
public getGraphInstance() {
return this.viewContainer.getG6Instance();
}
/**
* 隐藏某些组
* @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;
}
});
}
/**
*
*/
public getAllModels(): SVModel[] {
const modelList = Util.convertGroupTable2ModelList(this.modelConstructor.getLayoutGroupTable());
const accumulateLeakModels = this.viewContainer.getAccumulateLeakModels();
return [...modelList, ...accumulateLeakModels];
}
/**
* 根据配置变化更新视图
* @param modelType
* @returns
*/
public updateStyle(group: string, newOptions: LayoutGroupOptions) {
const models = this.getAllModels(),
layoutGroup = this.modelConstructor.getLayoutGroupTable().get(group);
layoutGroup.options = newOptions;
models.forEach(item => {
if (item.group !== group) {
return;
}
const modelType = item.getModelType(),
optionsType = layoutGroup.options[modelType];
if (optionsType) {
if (modelType === 'addressLabel') {
item.updateG6ModelStyle(item.generateG6ModelProps(optionsType));
}
else {
const targetModelOption = optionsType[item.sourceType];
if (targetModelOption) {
item.updateG6ModelStyle(item.generateG6ModelProps(targetModelOption));
}
}
}
});
}
/**
* 使用id查找某个节点
* @param id
*/
public findNode(id: string): SVNode {
const modelList = this.getAllModels();
const stringId = id.toString();
const targetNode: SVNode = modelList.find(item => item instanceof SVNode && item.sourceId === stringId) as SVNode;
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 as G6Event, event => {
callback(event.item['SVModel']);
});
}
/**
* 开启/关闭框选模式
* @param enable
*/
public switchBrushSelect(enable: boolean) {
const g6Instance = this.viewContainer.getG6Instance();
enable ? g6Instance.setMode('brush') : g6Instance.setMode('default');
}
/**
* 销毁引擎
*/
public destroy() {
this.modelConstructor.destroy();
this.viewContainer.destroy();
}
};