feat:增加布局模式
This commit is contained in:
parent
54a4a98e75
commit
f85f8beecd
@ -182,7 +182,7 @@ export function SolveDragCanvasWithLeak(viewContainer: ViewContainer) {
|
|||||||
let translateY = event.matrix[7],
|
let translateY = event.matrix[7],
|
||||||
dy = translateY - viewContainer.lastLeakAreaTranslateY;
|
dy = translateY - viewContainer.lastLeakAreaTranslateY;
|
||||||
|
|
||||||
viewContainer.lastLeakAreaTranslateY = translateY;
|
viewContainer.lastLeakAreaTranslateY = translateY;
|
||||||
|
|
||||||
viewContainer.leakAreaY = viewContainer.leakAreaY + dy;
|
viewContainer.leakAreaY = viewContainer.leakAreaY + dy;
|
||||||
if (viewContainer.hasLeak) {
|
if (viewContainer.hasLeak) {
|
||||||
|
|||||||
@ -49,7 +49,6 @@ export class ModelConstructor {
|
|||||||
const layoutGroupTable = new Map<string, LayoutGroup>(),
|
const layoutGroupTable = new Map<string, LayoutGroup>(),
|
||||||
layoutMap: { [key: string]: LayoutCreator } = SV.registeredLayout;
|
layoutMap: { [key: string]: LayoutCreator } = SV.registeredLayout;
|
||||||
|
|
||||||
|
|
||||||
Object.keys(sources).forEach(group => {
|
Object.keys(sources).forEach(group => {
|
||||||
let sourceGroup = sources[group],
|
let sourceGroup = sources[group],
|
||||||
layout = sourceGroup.layouter,
|
layout = sourceGroup.layouter,
|
||||||
@ -303,7 +302,6 @@ export class ModelConstructor {
|
|||||||
if (!markerData) continue;
|
if (!markerData) continue;
|
||||||
|
|
||||||
let id = `[${name}(${Array.isArray(markerData) ? markerData.join('-') : markerData})]`,
|
let id = `[${name}(${Array.isArray(markerData) ? markerData.join('-') : markerData})]`,
|
||||||
|
|
||||||
marker = new SVMarker(id, name, group, layout, markerData, node, markerOptions[name]);
|
marker = new SVMarker(id, name, group, layout, markerData, node, markerOptions[name]);
|
||||||
|
|
||||||
markerList.push(marker);
|
markerList.push(marker);
|
||||||
@ -351,7 +349,6 @@ export class ModelConstructor {
|
|||||||
): SVNode {
|
): SVNode {
|
||||||
let label: string | string[] = this.resolveNodeLabel(options.label, sourceNode),
|
let label: string | string[] = this.resolveNodeLabel(options.label, sourceNode),
|
||||||
id = `${sourceNodeType}(${sourceNode.id.toString()})`,
|
id = `${sourceNodeType}(${sourceNode.id.toString()})`,
|
||||||
|
|
||||||
node = new SVNode(id, sourceNodeType, group, layout, sourceNode, label, options);
|
node = new SVNode(id, sourceNodeType, group, layout, sourceNode, label, options);
|
||||||
|
|
||||||
if (node.freed) {
|
if (node.freed) {
|
||||||
@ -444,17 +441,17 @@ export class ModelConstructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 为了可以连接到不同group的结点
|
// 为了可以连接到不同group的结点
|
||||||
for (let layoutGroup of layoutGroupTable.values()) {
|
for (let layoutGroup of layoutGroupTable.values()) {
|
||||||
nodeList = layoutGroup.node.filter(item => item.sourceType === sourceNodeType);
|
nodeList = layoutGroup.node.filter(item => item.sourceType === sourceNodeType);
|
||||||
if (nodeList === undefined) {
|
if (nodeList === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
targetNode = nodeList.find(item => item.sourceId === targetId);
|
targetNode = nodeList.find(item => item.sourceId === targetId);
|
||||||
if (targetNode) {
|
if (targetNode) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// nodeList = layoutGroupTable.get(targetGroupName).node.filter(item => item.sourceType === sourceNodeType);
|
// nodeList = layoutGroupTable.get(targetGroupName).node.filter(item => item.sourceType === sourceNodeType);
|
||||||
|
|
||||||
// // 若目标node不存在,返回null
|
// // 若目标node不存在,返回null
|
||||||
@ -509,25 +506,25 @@ export class ModelConstructor {
|
|||||||
return node1.group === node2.group;
|
return node1.group === node2.group;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取簇
|
* 获取簇
|
||||||
* - 什么为一个簇?有边相连的一堆节点,再加上这些节点各自的appendages,共同组成了一个簇
|
* - 什么为一个簇?有边相连的一堆节点,再加上这些节点各自的appendages,共同组成了一个簇
|
||||||
* @param models
|
* @param models
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
static getClusters(models: SVModel[]): Group[] {
|
static getClusters(models: SVModel[]): Group[] {
|
||||||
const clusterGroupList = [],
|
const clusterGroupList = [],
|
||||||
idMap = {},
|
idMap = {},
|
||||||
idName = '__clusterId';
|
idName = '__clusterId';
|
||||||
|
|
||||||
models.forEach(item => {
|
models.forEach(item => {
|
||||||
idMap[item.id] = item;
|
idMap[item.id] = item;
|
||||||
});
|
});
|
||||||
|
|
||||||
const DFS = (model: SVModel, clusterId: number, idMap): SVModel[] => {
|
const DFS = (model: SVModel, clusterId: number, idMap): SVModel[] => {
|
||||||
if(model === null) {
|
if (model === null) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idMap[model.id] === undefined) {
|
if (idMap[model.id] === undefined) {
|
||||||
return [];
|
return [];
|
||||||
@ -560,7 +557,7 @@ export class ModelConstructor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (model instanceof SVNodeAppendage) {
|
if (model instanceof SVNodeAppendage) {
|
||||||
list.push(...DFS(model.target, clusterId, idMap));
|
list.push(...DFS(model.target, clusterId, idMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
@ -570,7 +567,7 @@ export class ModelConstructor {
|
|||||||
const model = models[i];
|
const model = models[i];
|
||||||
|
|
||||||
if (model[idName] !== undefined) {
|
if (model[idName] !== undefined) {
|
||||||
delete model[idName];
|
delete model[idName];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,7 +579,7 @@ export class ModelConstructor {
|
|||||||
});
|
});
|
||||||
|
|
||||||
clusterGroupList.push(group);
|
clusterGroupList.push(group);
|
||||||
delete model[idName];
|
delete model[idName];
|
||||||
}
|
}
|
||||||
|
|
||||||
return clusterGroupList;
|
return clusterGroupList;
|
||||||
|
|||||||
@ -1,116 +1,95 @@
|
|||||||
import { Util, Item } from '@antv/g6';
|
import { Util, Item } from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
export type animationConfig = {
|
export type animationConfig = {
|
||||||
duration: number;
|
duration: number;
|
||||||
timingFunction: string;
|
timingFunction: string;
|
||||||
callback?: () => void;
|
callback?: () => void;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动画表
|
* 动画表
|
||||||
*/
|
*/
|
||||||
export const Animations = {
|
export const Animations = {
|
||||||
|
/**
|
||||||
|
* 添加节点 / 边时的动画效果
|
||||||
|
* @param G6Item
|
||||||
|
* @param animationConfig
|
||||||
|
*/
|
||||||
|
APPEND(G6Item: Item, animationConfig: animationConfig) {
|
||||||
|
const type = G6Item.getType(),
|
||||||
|
group = G6Item.getContainer(),
|
||||||
|
Mat3 = Util.mat3,
|
||||||
|
animateCfg = {
|
||||||
|
duration: animationConfig.duration,
|
||||||
|
easing: animationConfig.timingFunction,
|
||||||
|
callback: animationConfig.callback,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
if (type === 'node') {
|
||||||
* 添加节点 / 边时的动画效果
|
let matrix = group.getMatrix(),
|
||||||
* @param G6Item
|
targetMatrix = Mat3.clone(matrix);
|
||||||
* @param animationConfig
|
|
||||||
*/
|
|
||||||
APPEND(G6Item: Item, animationConfig: animationConfig) {
|
|
||||||
const type = G6Item.getType(),
|
|
||||||
group = G6Item.getContainer(),
|
|
||||||
Mat3 = Util.mat3,
|
|
||||||
animateCfg = {
|
|
||||||
duration: animationConfig.duration,
|
|
||||||
easing: animationConfig.timingFunction,
|
|
||||||
callback: animationConfig.callback
|
|
||||||
};
|
|
||||||
|
|
||||||
if (type === 'node') {
|
Mat3.scale(matrix, matrix, [0, 0]);
|
||||||
let matrix = group.getMatrix(),
|
Mat3.scale(targetMatrix, targetMatrix, [1, 1]);
|
||||||
targetMatrix = Mat3.clone(matrix);
|
|
||||||
|
|
||||||
Mat3.scale(matrix, matrix, [0, 0]);
|
group.attr({ matrix, opacity: 0 });
|
||||||
Mat3.scale(targetMatrix, targetMatrix, [1, 1]);
|
group.animate({ matrix: targetMatrix, opacity: 1 }, animateCfg);
|
||||||
|
}
|
||||||
|
|
||||||
group.attr({ matrix, opacity: 0 });
|
if (type === 'edge') {
|
||||||
group.animate({ matrix: targetMatrix, opacity: 1 }, animateCfg);
|
const line = group.get('children')[0],
|
||||||
}
|
length = line.getTotalLength();
|
||||||
|
|
||||||
if (type === 'edge') {
|
line.attr({ lineDash: [0, length], opacity: 0 });
|
||||||
const line = group.get('children')[0],
|
line.animate({ lineDash: [length, 0], opacity: 1 }, animateCfg);
|
||||||
length = line.getTotalLength();
|
}
|
||||||
|
},
|
||||||
|
|
||||||
line.attr({ lineDash: [0, length], opacity: 0 });
|
/**
|
||||||
line.animate({ lineDash: [length, 0], opacity: 1 }, animateCfg);
|
* 移除节点 / 边时的动画效果
|
||||||
}
|
* @param G6Item
|
||||||
},
|
* @param animationConfig
|
||||||
|
*/
|
||||||
|
REMOVE(G6Item: Item, animationConfig: animationConfig) {
|
||||||
|
const type = G6Item.getType(),
|
||||||
|
group = G6Item.getContainer(),
|
||||||
|
Mat3 = Util.mat3,
|
||||||
|
animateCfg = {
|
||||||
|
duration: animationConfig.duration,
|
||||||
|
easing: animationConfig.timingFunction,
|
||||||
|
callback: animationConfig.callback,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
if (type === 'node') {
|
||||||
* 移除节点 / 边时的动画效果
|
let matrix = Mat3.clone(group.getMatrix());
|
||||||
* @param G6Item
|
|
||||||
* @param animationConfig
|
|
||||||
*/
|
|
||||||
REMOVE(G6Item: Item, animationConfig: animationConfig) {
|
|
||||||
const type = G6Item.getType(),
|
|
||||||
group = G6Item.getContainer(),
|
|
||||||
Mat3 = Util.mat3,
|
|
||||||
animateCfg = {
|
|
||||||
duration: animationConfig.duration,
|
|
||||||
easing: animationConfig.timingFunction,
|
|
||||||
callback: animationConfig.callback
|
|
||||||
};
|
|
||||||
|
|
||||||
if (type === 'node') {
|
Mat3.scale(matrix, matrix, [0, 0]);
|
||||||
let matrix = Mat3.clone(group.getMatrix());
|
group.animate({ opacity: 0, matrix }, animateCfg);
|
||||||
|
}
|
||||||
|
|
||||||
Mat3.scale(matrix, matrix, [0, 0]);
|
if (type === 'edge') {
|
||||||
group.animate({ opacity: 0, matrix }, animateCfg);
|
const line = group.get('children')[0],
|
||||||
}
|
length = line.getTotalLength();
|
||||||
|
|
||||||
if (type === 'edge') {
|
line.animate({ lineDash: [0, length], opacity: 0 }, animateCfg);
|
||||||
const line = group.get('children')[0],
|
}
|
||||||
length = line.getTotalLength();
|
},
|
||||||
|
|
||||||
line.animate({ lineDash: [0, length], opacity: 0 }, animateCfg);
|
/**
|
||||||
}
|
*
|
||||||
},
|
* @param G6Item
|
||||||
|
* @param animationConfig
|
||||||
|
*/
|
||||||
|
FADE_IN(G6Item: Item, animationConfig: animationConfig) {
|
||||||
|
const group = G6Item.getContainer(),
|
||||||
|
animateCfg = {
|
||||||
|
duration: animationConfig.duration,
|
||||||
|
easing: animationConfig.timingFunction,
|
||||||
|
callback: animationConfig.callback,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
group.attr({ opacity: 0 });
|
||||||
*
|
group.animate({ opacity: 1 }, animateCfg);
|
||||||
* @param G6Item
|
},
|
||||||
* @param animationConfig
|
|
||||||
*/
|
|
||||||
FADE_IN(G6Item: Item, animationConfig: animationConfig) {
|
|
||||||
const group = G6Item.getContainer(),
|
|
||||||
animateCfg = {
|
|
||||||
duration: animationConfig.duration,
|
|
||||||
easing: animationConfig.timingFunction,
|
|
||||||
callback: animationConfig.callback
|
|
||||||
};
|
|
||||||
|
|
||||||
group.attr({ opacity: 0 });
|
|
||||||
group.animate({ opacity: 1 }, animateCfg);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,11 @@ import { SVAddressLabel, SVFreedLabel, SVIndexLabel, SVMarker } from '../Model/S
|
|||||||
import { AddressLabelOption, IndexLabelOption, LayoutOptions, MarkerOption, ViewOptions } from '../options';
|
import { AddressLabelOption, IndexLabelOption, LayoutOptions, MarkerOption, ViewOptions } from '../options';
|
||||||
import { ViewContainer } from './viewContainer';
|
import { ViewContainer } from './viewContainer';
|
||||||
|
|
||||||
|
export enum ELayoutMode {
|
||||||
|
HORIZONTAL = 'hor',
|
||||||
|
VERTICAL = 'ver',
|
||||||
|
}
|
||||||
|
|
||||||
export class LayoutProvider {
|
export class LayoutProvider {
|
||||||
private engine: Engine;
|
private engine: Engine;
|
||||||
private viewOptions: ViewOptions;
|
private viewOptions: ViewOptions;
|
||||||
@ -155,7 +160,7 @@ export class LayoutProvider {
|
|||||||
},
|
},
|
||||||
left: (nodeBound: BoundingRect, labelBound: BoundingRect, offset: number) => {
|
left: (nodeBound: BoundingRect, labelBound: BoundingRect, offset: number) => {
|
||||||
return {
|
return {
|
||||||
x: nodeBound.x - labelBound.width / 2- offset,
|
x: nodeBound.x - labelBound.width / 2 - offset,
|
||||||
y: nodeBound.y + nodeBound.height / 2,
|
y: nodeBound.y + nodeBound.height / 2,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -253,7 +258,7 @@ export class LayoutProvider {
|
|||||||
|
|
||||||
const clusters = ModelConstructor.getClusters(accumulateLeakModels);
|
const clusters = ModelConstructor.getClusters(accumulateLeakModels);
|
||||||
|
|
||||||
// 每一个簇从左往右布局就完事了,比之前的方法简单稳定很多
|
// 每一个簇从左往右布局就完事了,比之前的方法简单稳定很多
|
||||||
clusters.forEach(item => {
|
clusters.forEach(item => {
|
||||||
const bound = item.getBound(),
|
const bound = item.getBound(),
|
||||||
x = prevBound ? prevBound.x + prevBound.width + this.leakClusterXInterval : this.leakAreaXoffset,
|
x = prevBound ? prevBound.x + prevBound.width + this.leakClusterXInterval : this.leakAreaXoffset,
|
||||||
@ -268,29 +273,48 @@ export class LayoutProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 对所有组进行相互布局
|
* 对所有组进行相互布局
|
||||||
* @param modelGroupTable
|
* @param modelGroupList
|
||||||
|
* @param layoutMode 水平/垂直
|
||||||
*/
|
*/
|
||||||
private layoutGroups(modelGroupList: Group[]): Group {
|
private layoutGroups(modelGroupList: Group[], layoutMode: ELayoutMode): Group {
|
||||||
let wrapperGroup: Group = new Group(),
|
let wrapperGroup: Group = new Group(),
|
||||||
group: Group,
|
group: Group,
|
||||||
prevBound: BoundingRect,
|
prevBound: BoundingRect,
|
||||||
bound: BoundingRect,
|
bound: BoundingRect,
|
||||||
boundList: BoundingRect[] = [],
|
boundList: BoundingRect[] = [],
|
||||||
dx = 0;
|
groupPadding = this.viewOptions.groupPadding,
|
||||||
|
dx = 0,
|
||||||
|
dy = 0;
|
||||||
|
|
||||||
|
|
||||||
// 左往右布局
|
|
||||||
for (let i = 0; i < modelGroupList.length; i++) {
|
for (let i = 0; i < modelGroupList.length; i++) {
|
||||||
group = modelGroupList[i];
|
group = modelGroupList[i];
|
||||||
bound = group.getPaddingBound(this.viewOptions.groupPadding);
|
bound = group.getPaddingBound(groupPadding);
|
||||||
|
|
||||||
if (prevBound) {
|
// 左往右水平布局
|
||||||
dx = prevBound.x + prevBound.width - bound.x;
|
if (layoutMode === ELayoutMode.HORIZONTAL) {
|
||||||
} else {
|
if (prevBound) {
|
||||||
dx = bound.x;
|
dx = prevBound.x + prevBound.width - bound.x;
|
||||||
|
} else {
|
||||||
|
dx = bound.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
group.translate(dx, 0);
|
||||||
|
Bound.translate(bound, dx, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上到下垂直布局
|
||||||
|
if (layoutMode === ELayoutMode.VERTICAL) {
|
||||||
|
if (prevBound) {
|
||||||
|
dy = prevBound.y + prevBound.height - bound.y - groupPadding;
|
||||||
|
} else {
|
||||||
|
dy = bound.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
group.translate(0, dy);
|
||||||
|
Bound.translate(bound, 0, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
group.translate(dx, 0);
|
|
||||||
Bound.translate(bound, dx, 0);
|
|
||||||
boundList.push(bound);
|
boundList.push(bound);
|
||||||
wrapperGroup.add(group);
|
wrapperGroup.add(group);
|
||||||
prevBound = bound;
|
prevBound = bound;
|
||||||
@ -333,11 +357,11 @@ export class LayoutProvider {
|
|||||||
* @param layoutGroupTable
|
* @param layoutGroupTable
|
||||||
* @param accumulateLeakModels
|
* @param accumulateLeakModels
|
||||||
*/
|
*/
|
||||||
public layoutAll(layoutGroupTable: LayoutGroupTable, accumulateLeakModels: SVModel[]) {
|
public layoutAll(layoutGroupTable: LayoutGroupTable, accumulateLeakModels: SVModel[], layoutMode: ELayoutMode) {
|
||||||
this.preLayoutProcess(layoutGroupTable);
|
this.preLayoutProcess(layoutGroupTable);
|
||||||
|
|
||||||
const modelGroupList: Group[] = this.layoutModels(layoutGroupTable);
|
const modelGroupList: Group[] = this.layoutModels(layoutGroupTable);
|
||||||
const generalGroup: Group = this.layoutGroups(modelGroupList);
|
const generalGroup: Group = this.layoutGroups(modelGroupList, layoutMode);
|
||||||
|
|
||||||
this.layoutLeakArea(accumulateLeakModels);
|
this.layoutLeakArea(accumulateLeakModels);
|
||||||
|
|
||||||
|
|||||||
@ -256,10 +256,10 @@ export class Reconcile {
|
|||||||
let { duration, timingFunction } = this.engine.animationOptions;
|
let { duration, timingFunction } = this.engine.animationOptions;
|
||||||
|
|
||||||
appendModels.forEach(item => {
|
appendModels.forEach(item => {
|
||||||
const G6Item = item.G6Item;
|
const G6Item = item.G6Item;
|
||||||
|
|
||||||
if (item instanceof SVNodeAppendage) {
|
if (item instanceof SVNodeAppendage) {
|
||||||
G6Item.enableCapture(false);
|
G6Item.enableCapture(false);
|
||||||
|
|
||||||
// 先不显示泄漏区节点上面的地址文本
|
// 先不显示泄漏区节点上面的地址文本
|
||||||
if (item instanceof SVAddressLabel) {
|
if (item instanceof SVAddressLabel) {
|
||||||
@ -395,9 +395,7 @@ export class Reconcile {
|
|||||||
isDiffLeak: boolean
|
isDiffLeak: boolean
|
||||||
): DiffResult {
|
): DiffResult {
|
||||||
const continuousModels: SVModel[] = this.getContinuousModels(prevModelList, modelList);
|
const continuousModels: SVModel[] = this.getContinuousModels(prevModelList, modelList);
|
||||||
const leakModels: SVModel[] = isDiffLeak
|
const leakModels: SVModel[] = isDiffLeak ? [] : this.getLeakModels(layoutGroupTable, prevModelList, modelList);
|
||||||
? []
|
|
||||||
: this.getLeakModels(layoutGroupTable, prevModelList, modelList);
|
|
||||||
const appendModels: SVModel[] = this.getAppendModels(prevModelList, modelList, accumulateLeakModels);
|
const appendModels: SVModel[] = this.getAppendModels(prevModelList, modelList, accumulateLeakModels);
|
||||||
const removeModels: SVModel[] = this.getRemoveModels(prevModelList, modelList, accumulateLeakModels);
|
const removeModels: SVModel[] = this.getRemoveModels(prevModelList, modelList, accumulateLeakModels);
|
||||||
const updateModels: SVModel[] = [
|
const updateModels: SVModel[] = [
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Engine } from '../engine';
|
import { Engine } from '../engine';
|
||||||
import { LayoutProvider } from './layoutProvider';
|
import { ELayoutMode, LayoutProvider } from './layoutProvider';
|
||||||
import { LayoutGroupTable } from '../Model/modelConstructor';
|
import { LayoutGroupTable } from '../Model/modelConstructor';
|
||||||
import { Util } from '../Common/util';
|
import { Util } from '../Common/util';
|
||||||
import { SVModel } from '../Model/SVModel';
|
import { SVModel } from '../Model/SVModel';
|
||||||
@ -19,141 +19,140 @@ import {
|
|||||||
import { handleUpdate } from '../sources';
|
import { handleUpdate } from '../sources';
|
||||||
|
|
||||||
export class ViewContainer {
|
export class ViewContainer {
|
||||||
private engine: Engine;
|
private engine: Engine;
|
||||||
private layoutProvider: LayoutProvider;
|
private layoutProvider: LayoutProvider;
|
||||||
private reconcile: Reconcile;
|
private reconcile: Reconcile;
|
||||||
public renderer: Renderer;
|
public renderer: Renderer;
|
||||||
|
|
||||||
private layoutGroupTable: LayoutGroupTable;
|
private layoutGroupTable: LayoutGroupTable;
|
||||||
private prevModelList: SVModel[];
|
private prevModelList: SVModel[];
|
||||||
private accumulateLeakModels: SVModel[];
|
private accumulateLeakModels: SVModel[];
|
||||||
|
|
||||||
public hasLeak: boolean;
|
public hasLeak: boolean;
|
||||||
public leakAreaY: number;
|
public leakAreaY: number;
|
||||||
public lastLeakAreaTranslateY: number;
|
public lastLeakAreaTranslateY: number;
|
||||||
public brushSelectedModels: SVModel[]; // 保存框选过程中被选中的节点
|
public brushSelectedModels: SVModel[]; // 保存框选过程中被选中的节点
|
||||||
public clickSelectNode: SVNode; // 点击选中的节点
|
public clickSelectNode: SVNode; // 点击选中的节点
|
||||||
|
|
||||||
constructor(engine: Engine, DOMContainer: HTMLElement, isForce: boolean) {
|
constructor(engine: Engine, DOMContainer: HTMLElement, isForce: boolean) {
|
||||||
const behaviorsModes: Modes = InitG6Behaviors(engine, this);
|
const behaviorsModes: Modes = InitG6Behaviors(engine, this);
|
||||||
|
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
this.layoutProvider = new LayoutProvider(engine, this);
|
this.layoutProvider = new LayoutProvider(engine, this);
|
||||||
this.renderer = new Renderer(engine, DOMContainer, behaviorsModes, isForce);
|
this.renderer = new Renderer(engine, DOMContainer, behaviorsModes, isForce);
|
||||||
this.reconcile = new Reconcile(engine, this.renderer);
|
this.reconcile = new Reconcile(engine, this.renderer);
|
||||||
this.layoutGroupTable = new Map();
|
this.layoutGroupTable = new Map();
|
||||||
this.prevModelList = [];
|
this.prevModelList = [];
|
||||||
this.accumulateLeakModels = [];
|
this.accumulateLeakModels = [];
|
||||||
this.hasLeak = false; // 判断是否已经发生过泄漏
|
this.hasLeak = false; // 判断是否已经发生过泄漏
|
||||||
this.brushSelectedModels = [];
|
this.brushSelectedModels = [];
|
||||||
this.clickSelectNode = null;
|
this.clickSelectNode = null;
|
||||||
this.lastLeakAreaTranslateY = 0;
|
this.lastLeakAreaTranslateY = 0;
|
||||||
|
|
||||||
const g6Instance = this.renderer.getG6Instance(),
|
const g6Instance = this.renderer.getG6Instance(),
|
||||||
leakAreaHeight = this.engine.viewOptions.leakAreaHeight,
|
leakAreaHeight = this.engine.viewOptions.leakAreaHeight,
|
||||||
height = g6Instance.getHeight(),
|
height = g6Instance.getHeight(),
|
||||||
{ drag, zoom } = this.engine.behaviorOptions;
|
{ drag, zoom } = this.engine.behaviorOptions;
|
||||||
|
|
||||||
this.leakAreaY = height - leakAreaHeight;
|
this.leakAreaY = height - leakAreaHeight;
|
||||||
|
|
||||||
SolveNodeAppendagesDrag(this);
|
SolveNodeAppendagesDrag(this);
|
||||||
SolveBrushSelectDrag(this);
|
SolveBrushSelectDrag(this);
|
||||||
drag && SolveDragCanvasWithLeak(this);
|
drag && SolveDragCanvasWithLeak(this);
|
||||||
zoom && SolveZoomCanvasWithLeak(this);
|
zoom && SolveZoomCanvasWithLeak(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------
|
/**
|
||||||
|
* 对主视图进行重新布局
|
||||||
/**
|
*/
|
||||||
* 对主视图进行重新布局
|
reLayout(layoutMode: ELayoutMode) {
|
||||||
*/
|
const g6Instance = this.getG6Instance(),
|
||||||
reLayout() {
|
|
||||||
const g6Instance = this.getG6Instance(),
|
|
||||||
group = g6Instance.getGroup(),
|
group = g6Instance.getGroup(),
|
||||||
matrix = group.getMatrix(),
|
matrix = group.getMatrix(),
|
||||||
bound = group.getCanvasBBox();
|
bound = group.getCanvasBBox();
|
||||||
|
|
||||||
const { duration, enable, timingFunction } = this.engine.animationOptions;
|
const { duration, enable, timingFunction } = this.engine.animationOptions;
|
||||||
|
|
||||||
if (matrix) {
|
if (matrix) {
|
||||||
let dx = matrix[6],
|
let dx = matrix[6],
|
||||||
dy = matrix[7];
|
dy = matrix[7];
|
||||||
|
|
||||||
g6Instance.moveTo(bound.minX - dx, bound.minY - dy, enable, {
|
g6Instance.moveTo(bound.minX - dx, bound.minY - dy, enable, {
|
||||||
duration,
|
duration,
|
||||||
easing: timingFunction,
|
easing: timingFunction,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const leakAreaHeight = this.engine.viewOptions.leakAreaHeight,
|
const leakAreaHeight = this.engine.viewOptions.leakAreaHeight,
|
||||||
height = g6Instance.getHeight();
|
height = g6Instance.getHeight();
|
||||||
|
|
||||||
this.leakAreaY = height - leakAreaHeight;
|
this.leakAreaY = height - leakAreaHeight;
|
||||||
this.lastLeakAreaTranslateY = 0;
|
this.lastLeakAreaTranslateY = 0;
|
||||||
this.layoutProvider.layoutAll(this.layoutGroupTable, this.accumulateLeakModels);
|
this.layoutProvider.layoutAll(this.layoutGroupTable, this.accumulateLeakModels, layoutMode);
|
||||||
g6Instance.refresh();
|
g6Instance.refresh();
|
||||||
|
|
||||||
EventBus.emit('onLeakAreaUpdate', {
|
EventBus.emit('onLeakAreaUpdate', {
|
||||||
leakAreaY: this.leakAreaY,
|
leakAreaY: this.leakAreaY,
|
||||||
hasLeak: this.hasLeak,
|
hasLeak: this.hasLeak,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 g6 实例
|
* 获取 g6 实例
|
||||||
*/
|
*/
|
||||||
getG6Instance(): Graph {
|
getG6Instance(): Graph {
|
||||||
return this.renderer.getG6Instance();
|
return this.renderer.getG6Instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取泄漏区里面的元素
|
* 获取泄漏区里面的元素
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
getAccumulateLeakModels(): SVModel[] {
|
getAccumulateLeakModels(): SVModel[] {
|
||||||
return this.accumulateLeakModels;
|
return this.accumulateLeakModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
getLayoutGroupTable(): LayoutGroupTable {
|
getLayoutGroupTable(): LayoutGroupTable {
|
||||||
return this.layoutGroupTable;
|
return this.layoutGroupTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新视图
|
* 刷新视图
|
||||||
*/
|
*/
|
||||||
refresh() {
|
refresh() {
|
||||||
this.renderer.getG6Instance().refresh();
|
this.renderer.getG6Instance().refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重新调整容器尺寸
|
* 重新调整容器尺寸
|
||||||
* @param width
|
* @param width
|
||||||
* @param height
|
* @param height
|
||||||
*/
|
*/
|
||||||
resize(width: number, height: number) {
|
resize(width: number, height: number) {
|
||||||
const g6Instance = this.getG6Instance(),
|
const g6Instance = this.getG6Instance(),
|
||||||
prevContainerHeight = g6Instance.getHeight(),
|
prevContainerHeight = g6Instance.getHeight(),
|
||||||
globalGroup: Group = new Group();
|
globalGroup: Group = new Group();
|
||||||
|
|
||||||
globalGroup.add(...this.prevModelList, ...this.accumulateLeakModels);
|
globalGroup.add(...this.prevModelList, ...this.accumulateLeakModels);
|
||||||
this.renderer.changeSize(width, height);
|
this.renderer.changeSize(width, height);
|
||||||
|
|
||||||
const containerHeight = g6Instance.getHeight(),
|
const containerHeight = g6Instance.getHeight(),
|
||||||
dy = containerHeight - prevContainerHeight;
|
dy = containerHeight - prevContainerHeight;
|
||||||
|
|
||||||
globalGroup.translate(0, dy);
|
globalGroup.translate(0, dy);
|
||||||
this.renderer.refresh();
|
this.renderer.refresh();
|
||||||
|
|
||||||
this.leakAreaY += dy;
|
this.leakAreaY += dy;
|
||||||
EventBus.emit('onLeakAreaUpdate', {
|
EventBus.emit('onLeakAreaUpdate', {
|
||||||
leakAreaY: this.leakAreaY,
|
leakAreaY: this.leakAreaY,
|
||||||
hasLeak: this.hasLeak,
|
hasLeak: this.hasLeak,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -174,7 +173,11 @@ export class ViewContainer {
|
|||||||
* @param models
|
* @param models
|
||||||
* @param layoutFn
|
* @param layoutFn
|
||||||
*/
|
*/
|
||||||
render(layoutGroupTable: LayoutGroupTable, isSameSources: boolean, handleUpdate: handleUpdate,hasTriggerLastStep: boolean) {
|
render(
|
||||||
|
layoutGroupTable: LayoutGroupTable,
|
||||||
|
isSameSources: boolean,
|
||||||
|
handleUpdate: handleUpdate
|
||||||
|
) {
|
||||||
const modelList = Util.convertGroupTable2ModelList(layoutGroupTable);
|
const modelList = Util.convertGroupTable2ModelList(layoutGroupTable);
|
||||||
|
|
||||||
this.restoreHighlight([...modelList, ...this.accumulateLeakModels]);
|
this.restoreHighlight([...modelList, ...this.accumulateLeakModels]);
|
||||||
@ -184,8 +187,8 @@ export class ViewContainer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否需要进行泄漏区的比较
|
// 判断是否需要进行泄漏区的比较
|
||||||
let isDiffLeak = handleUpdate.isEnterFunction || hasTriggerLastStep;
|
let isDiffLeak = handleUpdate?.isEnterFunction || handleUpdate?.hasTriggerLastStep;
|
||||||
|
|
||||||
const diffResult = this.reconcile.diff(
|
const diffResult = this.reconcile.diff(
|
||||||
this.layoutGroupTable,
|
this.layoutGroupTable,
|
||||||
@ -193,7 +196,7 @@ export class ViewContainer {
|
|||||||
modelList,
|
modelList,
|
||||||
this.accumulateLeakModels,
|
this.accumulateLeakModels,
|
||||||
// handleUpdate?.isEnterFunction
|
// handleUpdate?.isEnterFunction
|
||||||
isDiffLeak
|
isDiffLeak
|
||||||
),
|
),
|
||||||
renderModelList = [...modelList, ...diffResult.REMOVE, ...diffResult.LEAKED, ...this.accumulateLeakModels];
|
renderModelList = [...modelList, ...diffResult.REMOVE, ...diffResult.LEAKED, ...this.accumulateLeakModels];
|
||||||
|
|
||||||
@ -215,9 +218,10 @@ export class ViewContainer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const layoutMode = this.engine.viewOptions.layoutMode;
|
||||||
this.accumulateLeakModels.push(...diffResult.LEAKED); // 对泄漏节点进行向后累积
|
this.accumulateLeakModels.push(...diffResult.LEAKED); // 对泄漏节点进行向后累积
|
||||||
this.renderer.build(renderModelList); // 首先在离屏canvas渲染先
|
this.renderer.build(renderModelList); // 首先在离屏canvas渲染先
|
||||||
this.layoutProvider.layoutAll(layoutGroupTable, this.accumulateLeakModels); // 进行布局(设置model的x,y,样式等)
|
this.layoutProvider.layoutAll(layoutGroupTable, this.accumulateLeakModels, layoutMode); // 进行布局(设置model的x,y,样式等)
|
||||||
|
|
||||||
this.beforeRender();
|
this.beforeRender();
|
||||||
this.renderer.render(renderModelList); // 渲染视图
|
this.renderer.render(renderModelList); // 渲染视图
|
||||||
|
|||||||
395
src/engine.ts
395
src/engine.ts
@ -1,229 +1,238 @@
|
|||||||
import { handleUpdate, Sources } from "./sources";
|
import { handleUpdate, Sources } from './sources';
|
||||||
import { LayoutGroupTable, ModelConstructor } from "./Model/modelConstructor";
|
import { LayoutGroupTable, ModelConstructor } from './Model/modelConstructor';
|
||||||
import { AnimationOptions, BehaviorOptions, EngineOptions, LayoutGroupOptions, ViewOptions } from "./options";
|
import { AnimationOptions, BehaviorOptions, EngineOptions, LayoutGroupOptions, ViewOptions } from './options';
|
||||||
import { EventBus } from "./Common/eventBus";
|
import { EventBus } from './Common/eventBus';
|
||||||
import { ViewContainer } from "./View/viewContainer";
|
import { ViewContainer } from './View/viewContainer';
|
||||||
import { SVNode } from "./Model/SVNode";
|
import { SVNode } from './Model/SVNode';
|
||||||
import { Util } from "./Common/util";
|
import { Util } from './Common/util';
|
||||||
import { SVModel } from "./Model/SVModel";
|
import { SVModel } from './Model/SVModel';
|
||||||
import { G6Event } from "@antv/g6";
|
import { G6Event } from '@antv/g6';
|
||||||
|
import { ELayoutMode } from './View/layoutProvider';
|
||||||
|
|
||||||
export class Engine {
|
export class Engine {
|
||||||
private modelConstructor: ModelConstructor;
|
private modelConstructor: ModelConstructor;
|
||||||
private viewContainer: ViewContainer;
|
private viewContainer: ViewContainer;
|
||||||
private prevStringSource: string;
|
private prevStringSource: string;
|
||||||
|
|
||||||
public engineOptions: EngineOptions;
|
public engineOptions: EngineOptions;
|
||||||
public viewOptions: ViewOptions;
|
public viewOptions: ViewOptions;
|
||||||
public animationOptions: AnimationOptions;
|
public animationOptions: AnimationOptions;
|
||||||
public behaviorOptions: BehaviorOptions;
|
public behaviorOptions: BehaviorOptions;
|
||||||
|
|
||||||
constructor(DOMContainer: HTMLElement, engineOptions: EngineOptions, isForce: boolean) {
|
constructor(DOMContainer: HTMLElement, engineOptions: EngineOptions, isForce: boolean) {
|
||||||
this.engineOptions = Object.assign({}, engineOptions);
|
this.engineOptions = Object.assign({}, engineOptions);
|
||||||
|
|
||||||
this.viewOptions = Object.assign({
|
this.viewOptions = Object.assign(
|
||||||
fitCenter: true,
|
{
|
||||||
fitView: false,
|
fitCenter: true,
|
||||||
groupPadding: 20,
|
fitView: false,
|
||||||
leakAreaHeight: 150,
|
groupPadding: 20,
|
||||||
updateHighlight: '#fc5185'
|
leakAreaHeight: 150,
|
||||||
}, engineOptions.view);
|
updateHighlight: '#fc5185',
|
||||||
|
layoutMode: ELayoutMode.HORIZONTAL
|
||||||
|
},
|
||||||
|
engineOptions.view
|
||||||
|
);
|
||||||
|
|
||||||
this.animationOptions = Object.assign({
|
this.animationOptions = Object.assign(
|
||||||
enable: true,
|
{
|
||||||
duration: 750,
|
enable: true,
|
||||||
timingFunction: 'easePolyOut'
|
duration: 750,
|
||||||
}, engineOptions.animation);
|
timingFunction: 'easePolyOut',
|
||||||
|
},
|
||||||
|
engineOptions.animation
|
||||||
|
);
|
||||||
|
|
||||||
this.behaviorOptions = Object.assign({
|
this.behaviorOptions = Object.assign(
|
||||||
drag: true,
|
{
|
||||||
zoom: true,
|
drag: true,
|
||||||
dragNode: true,
|
zoom: true,
|
||||||
selectNode: true
|
dragNode: true,
|
||||||
}, engineOptions.behavior);
|
selectNode: true,
|
||||||
|
},
|
||||||
|
engineOptions.behavior
|
||||||
|
);
|
||||||
|
|
||||||
this.modelConstructor = new ModelConstructor(this);
|
this.modelConstructor = new ModelConstructor(this);
|
||||||
this.viewContainer = new ViewContainer(this, DOMContainer, isForce);
|
this.viewContainer = new ViewContainer(this, DOMContainer, isForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入数据进行渲染
|
* 输入数据进行渲染
|
||||||
* @param sources
|
* @param sources
|
||||||
* @param prevStep
|
* @param prevStep
|
||||||
*/
|
*/
|
||||||
public render(source: Sources, hasTriggerLastStep: boolean) {
|
public render(source: Sources) {
|
||||||
let isSameSources: boolean = false,
|
let isSameSources: boolean = false,
|
||||||
layoutGroupTable: LayoutGroupTable;
|
layoutGroupTable: LayoutGroupTable;
|
||||||
|
|
||||||
if (source === undefined || source === null) {
|
if (source === undefined || source === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let handleUpdate: handleUpdate = source.handleUpdate,
|
let handleUpdate: handleUpdate = source.handleUpdate,
|
||||||
stringSource = JSON.stringify(source);
|
stringSource = JSON.stringify(source);
|
||||||
|
|
||||||
if (this.prevStringSource === stringSource) {
|
if (this.prevStringSource === stringSource) {
|
||||||
isSameSources = true;
|
isSameSources = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.prevStringSource = stringSource;
|
this.prevStringSource = stringSource;
|
||||||
|
|
||||||
|
if (isSameSources) {
|
||||||
|
// 若源数据两次一样的,用回上一次的layoutGroupTable
|
||||||
|
layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
|
||||||
|
} else {
|
||||||
|
// 1 转换模型(data => model)
|
||||||
|
layoutGroupTable = this.modelConstructor.construct(source);
|
||||||
|
}
|
||||||
|
|
||||||
if(isSameSources) {
|
// 2 渲染(使用g6进行渲染)
|
||||||
// 若源数据两次一样的,用回上一次的layoutGroupTable
|
this.viewContainer.render(layoutGroupTable, isSameSources, handleUpdate);
|
||||||
layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
// 1 转换模型(data => model)
|
|
||||||
layoutGroupTable = this.modelConstructor.construct(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 渲染(使用g6进行渲染)
|
/**
|
||||||
this.viewContainer.render(layoutGroupTable, isSameSources, handleUpdate, hasTriggerLastStep);
|
* 重新布局
|
||||||
}
|
*/
|
||||||
|
public reLayout(layoutMode?: ELayoutMode) {
|
||||||
|
this.viewOptions.layoutMode = layoutMode || this.viewOptions.layoutMode;
|
||||||
|
this.viewContainer.reLayout(this.viewOptions.layoutMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 G6 实例
|
||||||
|
*/
|
||||||
|
public getGraphInstance() {
|
||||||
|
return this.viewContainer.getG6Instance();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重新布局
|
* 隐藏某些组
|
||||||
*/
|
* @param groupNames
|
||||||
public reLayout() {
|
*/
|
||||||
this.viewContainer.reLayout();
|
public hideGroups(groupNames: string | string[]) {
|
||||||
}
|
const names = Array.isArray(groupNames) ? groupNames : [groupNames],
|
||||||
|
instance = this.viewContainer.getG6Instance(),
|
||||||
|
layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
|
||||||
|
|
||||||
/**
|
layoutGroupTable.forEach(item => {
|
||||||
* 获取 G6 实例
|
const hasName = names.find(name => name === item.layout);
|
||||||
*/
|
|
||||||
public getGraphInstance() {
|
|
||||||
return this.viewContainer.getG6Instance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (hasName && !item.isHide) {
|
||||||
* 隐藏某些组
|
item.modelList.forEach(model => instance.hideItem(model.G6Item));
|
||||||
* @param groupNames
|
item.isHide = true;
|
||||||
*/
|
}
|
||||||
public hideGroups(groupNames: string | string[]) {
|
|
||||||
const names = Array.isArray(groupNames) ? groupNames : [groupNames],
|
|
||||||
instance = this.viewContainer.getG6Instance(),
|
|
||||||
layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
|
|
||||||
|
|
||||||
layoutGroupTable.forEach(item => {
|
if (!hasName && item.isHide) {
|
||||||
const hasName = names.find(name => name === item.layout);
|
item.modelList.forEach(model => instance.showItem(model.G6Item));
|
||||||
|
item.isHide = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (hasName && !item.isHide) {
|
/**
|
||||||
item.modelList.forEach(model => instance.hideItem(model.G6Item));
|
*
|
||||||
item.isHide = true;
|
*/
|
||||||
}
|
public getAllModels(): SVModel[] {
|
||||||
|
const modelList = Util.convertGroupTable2ModelList(this.modelConstructor.getLayoutGroupTable());
|
||||||
|
const accumulateLeakModels = this.viewContainer.getAccumulateLeakModels();
|
||||||
|
|
||||||
if (!hasName && item.isHide) {
|
return [...modelList, ...accumulateLeakModels];
|
||||||
item.modelList.forEach(model => instance.showItem(model.G6Item));
|
}
|
||||||
item.isHide = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* 根据配置变化更新视图
|
||||||
*/
|
* @param modelType
|
||||||
public getAllModels(): SVModel[] {
|
* @returns
|
||||||
const modelList = Util.convertGroupTable2ModelList(this.modelConstructor.getLayoutGroupTable());
|
*/
|
||||||
const accumulateLeakModels = this.viewContainer.getAccumulateLeakModels();
|
public updateStyle(group: string, newOptions: LayoutGroupOptions) {
|
||||||
|
const models = this.getAllModels(),
|
||||||
|
layoutGroup = this.modelConstructor.getLayoutGroupTable().get(group);
|
||||||
|
|
||||||
return [...modelList, ...accumulateLeakModels];
|
layoutGroup.options = newOptions;
|
||||||
}
|
models.forEach(item => {
|
||||||
|
if (item.group !== group) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
const modelType = item.getModelType(),
|
||||||
* 根据配置变化更新视图
|
optionsType = layoutGroup.options[modelType];
|
||||||
* @param modelType
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
public updateStyle(group: string, newOptions: LayoutGroupOptions) {
|
|
||||||
const models = this.getAllModels(),
|
|
||||||
layoutGroup = this.modelConstructor.getLayoutGroupTable().get(group);
|
|
||||||
|
|
||||||
layoutGroup.options = newOptions;
|
if (optionsType) {
|
||||||
models.forEach(item => {
|
if (modelType === 'addressLabel') {
|
||||||
if (item.group !== group) {
|
item.updateG6ModelStyle(item.generateG6ModelProps(optionsType));
|
||||||
return;
|
} else {
|
||||||
}
|
const targetModelOption = optionsType[item.sourceType];
|
||||||
|
if (targetModelOption) {
|
||||||
|
item.updateG6ModelStyle(item.generateG6ModelProps(targetModelOption));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const modelType = item.getModelType(),
|
/**
|
||||||
optionsType = layoutGroup.options[modelType];
|
* 使用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;
|
||||||
|
|
||||||
if (optionsType) {
|
return targetNode;
|
||||||
if (modelType === 'addressLabel') {
|
}
|
||||||
item.updateG6ModelStyle(item.generateG6ModelProps(optionsType));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const targetModelOption = optionsType[item.sourceType];
|
|
||||||
if (targetModelOption) {
|
|
||||||
item.updateG6ModelStyle(item.generateG6ModelProps(targetModelOption));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用id查找某个节点
|
* 调整容器尺寸
|
||||||
* @param id
|
* @param width
|
||||||
*/
|
* @param height
|
||||||
public findNode(id: string): SVNode {
|
*/
|
||||||
const modelList = this.getAllModels();
|
public resize(width: number, height: number) {
|
||||||
const stringId = id.toString();
|
this.viewContainer.resize(width, height);
|
||||||
const targetNode: SVNode = modelList.find(item => item instanceof SVNode && item.sourceId === stringId) as SVNode;
|
}
|
||||||
|
|
||||||
return targetNode;
|
/**
|
||||||
}
|
* 绑定 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);
|
||||||
* @param width
|
return;
|
||||||
* @param height
|
}
|
||||||
*/
|
|
||||||
public resize(width: number, height: number) {
|
|
||||||
this.viewContainer.resize(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (eventName === 'onLeakAreaUpdate') {
|
||||||
* 绑定 G6 事件
|
EventBus.on(eventName, callback);
|
||||||
* @param eventName
|
return;
|
||||||
* @param callback
|
}
|
||||||
*/
|
|
||||||
public on(eventName: string, callback: Function) {
|
|
||||||
if (typeof callback !== 'function') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventName === 'onFreed' || eventName === 'onLeak') {
|
this.viewContainer.getG6Instance().on(eventName as G6Event, event => {
|
||||||
EventBus.on(eventName, callback);
|
callback(event.item['SVModel']);
|
||||||
return;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventName === 'onLeakAreaUpdate') {
|
/**
|
||||||
EventBus.on(eventName, callback);
|
* 开启/关闭框选模式
|
||||||
return;
|
* @param enable
|
||||||
}
|
*/
|
||||||
|
public switchBrushSelect(enable: boolean) {
|
||||||
|
const g6Instance = this.viewContainer.getG6Instance();
|
||||||
|
enable ? g6Instance.setMode('brush') : g6Instance.setMode('default');
|
||||||
|
}
|
||||||
|
|
||||||
this.viewContainer.getG6Instance().on(eventName as G6Event, event => {
|
/**
|
||||||
callback(event.item['SVModel']);
|
* 销毁引擎
|
||||||
});
|
*/
|
||||||
}
|
public destroy() {
|
||||||
|
this.modelConstructor.destroy();
|
||||||
/**
|
this.viewContainer.destroy();
|
||||||
* 开启/关闭框选模式
|
}
|
||||||
* @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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { SVModel } from "./Model/SVModel";
|
import { SVModel } from "./Model/SVModel";
|
||||||
import { SVNode } from "./Model/SVNode";
|
import { SVNode } from "./Model/SVNode";
|
||||||
import { SourceNode } from "./sources";
|
import { SourceNode } from "./sources";
|
||||||
|
import { ELayoutMode } from "./View/layoutProvider";
|
||||||
|
|
||||||
|
|
||||||
export interface Style {
|
export interface Style {
|
||||||
@ -104,6 +105,7 @@ export interface ViewOptions {
|
|||||||
groupPadding: number;
|
groupPadding: number;
|
||||||
updateHighlight: string;
|
updateHighlight: string;
|
||||||
leakAreaHeight: number;
|
leakAreaHeight: number;
|
||||||
|
layoutMode: ELayoutMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@ export interface SourceNode {
|
|||||||
export interface handleUpdate {
|
export interface handleUpdate {
|
||||||
isEnterFunction: boolean;
|
isEnterFunction: boolean;
|
||||||
isFirstDebug: boolean;
|
isFirstDebug: boolean;
|
||||||
|
hasTriggerLastStep: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Sources = {
|
export type Sources = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user