fix: 大量bug修复
This commit is contained in:
+1
-1
@@ -25,7 +25,7 @@ export const Util = {
|
||||
* @param obj
|
||||
*/
|
||||
objectClone<T extends Object>(obj: T): T {
|
||||
return obj? JSON.parse(JSON.stringify(obj)): { };
|
||||
return obj? JSON.parse(JSON.stringify(obj)): null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -102,7 +102,8 @@ export class SVModel {
|
||||
// 更新G6Item
|
||||
if (this.G6Item) {
|
||||
if (this.preLayout) {
|
||||
this.G6Item.getModel()[attr] = value;
|
||||
const G6ItemModel = this.G6Item.getModel();
|
||||
G6ItemModel[attr] = value;
|
||||
}
|
||||
else {
|
||||
this.g6Instance.updateItem(this.G6Item, this.G6ModelProps);
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ export class SVNode extends SVModel {
|
||||
}
|
||||
|
||||
protected generateG6ModelProps(options: NodeOption): NodeConfig {
|
||||
let indexOptions = Util.objectClone<NodeIndexOption>(options.indexOptions);
|
||||
let indexOptions = Util.objectClone<NodeIndexOption>(options.indexOptions) || { index: { position: 'bottom' } };
|
||||
|
||||
if (indexOptions) {
|
||||
Object.keys(indexOptions).map(key => {
|
||||
|
||||
@@ -43,13 +43,13 @@ export class ModelConstructor {
|
||||
*/
|
||||
public construct(sources: Sources): LayoutGroupTable {
|
||||
const layoutGroupTable = new Map<string, LayoutGroup>(),
|
||||
layoutMap: { [key: string]: LayoutCreator } = SV.registeredLayout,
|
||||
optionsTable = this.engine.optionsTable;
|
||||
layoutMap: { [key: string]: { [key: string]: LayoutCreator } } = SV.registeredLayout;
|
||||
|
||||
Object.keys(sources).forEach(group => {
|
||||
let sourceGroup = sources[group],
|
||||
layout = sourceGroup.layouter,
|
||||
layoutCreator: LayoutCreator = layoutMap[layout];
|
||||
mode = sourceGroup.mode || 'default',
|
||||
layoutCreator: LayoutCreator = layoutMap[layout][mode];
|
||||
|
||||
if (!layout || !layoutCreator) {
|
||||
return;
|
||||
@@ -66,7 +66,7 @@ export class ModelConstructor {
|
||||
return;
|
||||
}
|
||||
|
||||
const options: LayoutGroupOptions = optionsTable[layout],
|
||||
const options: LayoutGroupOptions = layoutCreator.defineOptions(sourceGroup.data),
|
||||
sourceData = layoutCreator.sourcesPreprocess(sourceGroup.data, options),
|
||||
nodeOptions = options.node || options['element'] || {},
|
||||
markerOptions = options.marker || {};
|
||||
@@ -396,5 +396,6 @@ export class ModelConstructor {
|
||||
*/
|
||||
destroy() {
|
||||
this.layoutGroupTable = null;
|
||||
this.prevSourcesStringMap = null;
|
||||
}
|
||||
};
|
||||
+7
-3
@@ -26,7 +26,7 @@ export interface StructV {
|
||||
|
||||
registeredShape: any[];
|
||||
|
||||
registeredLayout: { [key: string]: LayoutCreator },
|
||||
registeredLayout: { [key: string]: { [key: string]: LayoutCreator } },
|
||||
|
||||
registerShape: Function,
|
||||
|
||||
@@ -61,7 +61,7 @@ SV.registeredShape = [
|
||||
];
|
||||
|
||||
SV.registerShape = G6.registerNode;
|
||||
SV.registerLayout = function(name: string, layoutCreator: LayoutCreator) {
|
||||
SV.registerLayout = function(name: string, layoutCreator: LayoutCreator, mode: string = 'default') {
|
||||
|
||||
if(typeof layoutCreator.sourcesPreprocess !== 'function') {
|
||||
layoutCreator.sourcesPreprocess = function(data: SourceNode[]): SourceNode[] {
|
||||
@@ -78,8 +78,12 @@ SV.registerLayout = function(name: string, layoutCreator: LayoutCreator) {
|
||||
if(typeof layoutCreator.defineOptions !== 'function' || typeof layoutCreator.layout !== 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
if(SV.registeredLayout[name] === undefined) {
|
||||
SV.registeredLayout[name] = {};
|
||||
}
|
||||
|
||||
SV.registeredLayout[name] = layoutCreator;
|
||||
SV.registeredLayout[name][mode] = layoutCreator;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -265,6 +265,7 @@ export class LayoutProvider {
|
||||
* @param layoutGroupTable
|
||||
* @param leakModels
|
||||
* @param hasLeak
|
||||
* @param needFitCenter
|
||||
*/
|
||||
public layoutAll(layoutGroupTable: LayoutGroupTable, accumulateLeakModels: SVModel[], leakModels: SVModel[]) {
|
||||
this.preLayoutProcess(layoutGroupTable);
|
||||
|
||||
+14
-1
@@ -25,11 +25,13 @@ export class Reconcile {
|
||||
|
||||
private engine: Engine;
|
||||
private renderer: Renderer;
|
||||
private prevChangeModels: SVModel[];
|
||||
private isFirstPatch: boolean;
|
||||
|
||||
constructor(engine: Engine, renderer: Renderer) {
|
||||
this.engine = engine;
|
||||
this.renderer = renderer;
|
||||
this.prevChangeModels = [];
|
||||
this.isFirstPatch = true;
|
||||
}
|
||||
|
||||
@@ -316,6 +318,10 @@ export class Reconcile {
|
||||
* @param models
|
||||
*/
|
||||
private handleChangeModels(models: SVModel[]) {
|
||||
if(models.length === 0) {
|
||||
models = this.prevChangeModels;
|
||||
}
|
||||
|
||||
const changeHighlightColor: string = this.engine.viewOptions.updateHighlight;
|
||||
|
||||
if (!changeHighlightColor || typeof changeHighlightColor !== 'string') {
|
||||
@@ -338,6 +344,8 @@ export class Reconcile {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.prevChangeModels = models;
|
||||
}
|
||||
|
||||
|
||||
@@ -389,6 +397,8 @@ export class Reconcile {
|
||||
ACCUMULATE_LEAK
|
||||
} = diffResult;
|
||||
|
||||
this.handleAccumulateLeakModels(ACCUMULATE_LEAK);
|
||||
|
||||
// 第一次渲染的时候不高亮变化的元素
|
||||
if (this.isFirstPatch === false) {
|
||||
this.handleChangeModels(UPDATE);
|
||||
@@ -399,10 +409,13 @@ export class Reconcile {
|
||||
this.handleAppendModels(APPEND);
|
||||
this.handleLeakModels(LEAKED);
|
||||
this.handleRemoveModels(REMOVE);
|
||||
this.handleAccumulateLeakModels(ACCUMULATE_LEAK);
|
||||
|
||||
if(this.isFirstPatch) {
|
||||
this.isFirstPatch = false;
|
||||
}
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.prevChangeModels.length = 0;
|
||||
}
|
||||
}
|
||||
@@ -115,6 +115,9 @@ export class Renderer {
|
||||
item.G6Item = this.g6Instance.findById(item.id);
|
||||
item.G6Item['SVModel'] = item;
|
||||
});
|
||||
|
||||
this.g6Instance.getEdges().forEach(item => item.toFront());
|
||||
this.g6Instance.paint();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+21
-13
@@ -61,8 +61,19 @@ export class ViewContainer {
|
||||
* 对主视图进行重新布局
|
||||
*/
|
||||
reLayout() {
|
||||
this.layoutProvider.layoutAll(this.prevLayoutGroupTable, [], this.accumulateLeakModels);
|
||||
this.getG6Instance().refresh();
|
||||
const g6Instance = this.getG6Instance(),
|
||||
group = g6Instance.getGroup(),
|
||||
matrix = group.getMatrix();
|
||||
|
||||
if (matrix) {
|
||||
let dx = matrix[6],
|
||||
dy = matrix[7];
|
||||
|
||||
g6Instance.translate(-dx, -dy);
|
||||
}
|
||||
|
||||
this.layoutProvider.layoutAll(this.prevLayoutGroupTable, this.accumulateLeakModels, []);
|
||||
g6Instance.refresh();
|
||||
}
|
||||
|
||||
|
||||
@@ -156,6 +167,11 @@ export class ViewContainer {
|
||||
*/
|
||||
destroy() {
|
||||
this.renderer.destroy();
|
||||
this.reconcile.destroy();
|
||||
this.layoutProvider = null;
|
||||
this.prevLayoutGroupTable = null;
|
||||
this.prevModelList.length = 0;
|
||||
this.accumulateLeakModels.length = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -163,15 +179,9 @@ export class ViewContainer {
|
||||
|
||||
|
||||
/**
|
||||
* 把渲染前要触发的逻辑放在这里
|
||||
* 把渲染后要触发的逻辑放在这里
|
||||
*/
|
||||
private afterRender() {
|
||||
const g6Instance = this.renderer.getG6Instance();
|
||||
|
||||
// 把所有连线置顶
|
||||
g6Instance.getEdges().forEach(item => item.toFront());
|
||||
g6Instance.paint();
|
||||
|
||||
this.prevModelList.forEach(item => {
|
||||
if (item.leaked === false) {
|
||||
item.discarded = true;
|
||||
@@ -180,11 +190,9 @@ export class ViewContainer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 把渲染后要触发的逻辑放在这里
|
||||
* 把渲染前要触发的逻辑放在这里
|
||||
*/
|
||||
private beforeRender() {
|
||||
|
||||
}
|
||||
private beforeRender() { }
|
||||
}
|
||||
|
||||
|
||||
|
||||
+36
-23
@@ -1,6 +1,6 @@
|
||||
import { Sources } from "./sources";
|
||||
import { ModelConstructor } from "./Model/modelConstructor";
|
||||
import { AnimationOptions, EngineOptions, InteractionOptions, LayoutGroupOptions, ViewOptions } from "./options";
|
||||
import { AnimationOptions, EngineOptions, InteractionOptions, ViewOptions } from "./options";
|
||||
import { SV } from "./StructV";
|
||||
import { EventBus } from "./Common/eventBus";
|
||||
import { ViewContainer } from "./View/viewContainer";
|
||||
@@ -11,18 +11,16 @@ import { SVMarker } from "./Model/SVMarker";
|
||||
|
||||
export class Engine {
|
||||
private modelConstructor: ModelConstructor;
|
||||
private viewContainer: ViewContainer
|
||||
private prevStringSourceData: string;
|
||||
private viewContainer: ViewContainer;
|
||||
private prevSource: Sources;
|
||||
private prevStringSource: 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({
|
||||
@@ -46,40 +44,55 @@ export class Engine {
|
||||
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
|
||||
* @param sources
|
||||
*/
|
||||
public render(sourceData: Sources) {
|
||||
if(sourceData === undefined || sourceData === null) {
|
||||
public render(source: Sources) {
|
||||
if(source === undefined || source === null) {
|
||||
return;
|
||||
}
|
||||
``
|
||||
let stringSource = JSON.stringify(source);
|
||||
if(this.prevStringSource === stringSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
let stringSourceData = JSON.stringify(sourceData);
|
||||
if(this.prevStringSourceData === stringSourceData) {
|
||||
return;
|
||||
}
|
||||
this.prevStringSourceData = stringSourceData;
|
||||
this.prevSource = source;
|
||||
this.prevStringSource = stringSource;
|
||||
|
||||
// 1 转换模型(data => model)
|
||||
const layoutGroupTable = this.modelConstructor.construct(sourceData);
|
||||
const layoutGroupTable = this.modelConstructor.construct(source);
|
||||
|
||||
// 2 渲染(使用g6进行渲染)
|
||||
this.viewContainer.render(layoutGroupTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换指定数据结构的 mode 主题
|
||||
* @param mode
|
||||
*/
|
||||
public switchMode(layout: string, mode: string) {
|
||||
if(this.prevSource === undefined || this.prevSource === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object.keys(this.prevSource).map(group => {
|
||||
let sourceGroup = this.prevSource[group];
|
||||
|
||||
if(sourceGroup.layouter === layout) {
|
||||
sourceGroup.mode = mode;
|
||||
}
|
||||
});
|
||||
|
||||
this.render(this.prevSource);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重新布局
|
||||
*/
|
||||
|
||||
+2
-2
@@ -118,8 +118,8 @@ export interface EngineOptions {
|
||||
|
||||
|
||||
export interface LayoutCreator {
|
||||
defineOptions(): LayoutGroupOptions;
|
||||
sourcesPreprocess?(sources: SourceNode[], options: LayoutGroupOptions): SourceNode[];
|
||||
defineOptions(sourceData: SourceNode[]): LayoutGroupOptions;
|
||||
sourcesPreprocess?(sourceData: SourceNode[], options: LayoutGroupOptions): SourceNode[];
|
||||
defineLeakRule?(nodes: SVNode[]): SVNode[];
|
||||
layout(nodes: SVNode[], layoutOptions: LayoutOptions);
|
||||
[key: string]: any;
|
||||
|
||||
+5
-1
@@ -16,7 +16,11 @@ export interface SourceNode {
|
||||
|
||||
|
||||
export type Sources = {
|
||||
[key: string]: { data: SourceNode[]; layouter: string; }
|
||||
[key: string]: {
|
||||
data: SourceNode[];
|
||||
layouter: string;
|
||||
mode?: string
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user