修复泄漏节点计算的bug
This commit is contained in:
parent
a7d9aed4ab
commit
efe430ca48
@ -39,24 +39,26 @@
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container" id="container"></div>
|
||||
<div class="container" id="container">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<button id="btn">change</button>
|
||||
<button id="btn-next">reLayout</button>
|
||||
<button id="btn-set">set</button>
|
||||
|
||||
<span id="pos"></span>
|
||||
|
||||
<div class="down">
|
||||
<div class="down container">
|
||||
<div id="freed"></div>
|
||||
<div id="leak"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="./../dist/sv.js"></script>
|
||||
<script>
|
||||
|
||||
@ -130,8 +132,6 @@ container.addEventListener('mousemove', e => {
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
2
dist/sv.js
vendored
2
dist/sv.js
vendored
File diff suppressed because one or more lines are too long
@ -87,21 +87,16 @@ export const Animations = {
|
||||
* @param model
|
||||
* @param animationConfig
|
||||
*/
|
||||
animate_moveTo(model: Model, animationConfig: animationConfig) {
|
||||
animate_fadeOut(model: Model, animationConfig: animationConfig) {
|
||||
const G6Item = model.G6Item,
|
||||
group = G6Item.getContainer(),
|
||||
Mat3 = SV.Mat3,
|
||||
target = animationConfig.payload,
|
||||
animateCfg = {
|
||||
duration: animationConfig.duration,
|
||||
duration: 1200,
|
||||
easing: animationConfig.timingFunction,
|
||||
callback: animationConfig.callback
|
||||
};
|
||||
|
||||
let matrix = Mat3.clone(group.getMatrix());
|
||||
|
||||
Mat3.translate(matrix, matrix, [target.x, target.y]);
|
||||
group.animate({ opacity: 0, matrix }, animateCfg);
|
||||
group.animate({ opacity: 0 }, animateCfg);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { Engine } from "../../engine";
|
||||
import { Link, Model } from "../../Model/modelData";
|
||||
import { InteractionOptions, LayoutGroupOptions } from "../../options";
|
||||
import { Animations } from "../animation";
|
||||
import { Container } from "./container";
|
||||
|
||||
|
||||
@ -8,7 +10,39 @@ import { Container } from "./container";
|
||||
* 主可视化视图
|
||||
*/
|
||||
export class MainContainer extends Container {
|
||||
private leakContainerPosition: { x: number, y: number } = null;
|
||||
private freedContainerPosition: { x: number, y: number } = null;
|
||||
|
||||
constructor(engine: Engine, DOMContainer: HTMLElement, g6Options: { [key: string]: any } = { }) {
|
||||
super(engine, DOMContainer, g6Options);
|
||||
|
||||
this.leakContainerPosition = this.getDOMPosition(this.engine.engineOptions.leakContainer);
|
||||
this.freedContainerPosition = this.getDOMPosition(this.engine.engineOptions.freedContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dom
|
||||
* @returns
|
||||
*/
|
||||
private getDOMPosition(dom: HTMLElement): { x: number, y: number } {
|
||||
if(dom === null) {
|
||||
return { x: 0, y: 0 };
|
||||
}
|
||||
|
||||
const bound = dom.getBoundingClientRect();
|
||||
|
||||
return {
|
||||
x: bound.x + bound.width / 2,
|
||||
y: bound.y + bound.height / 2
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param optionsTable
|
||||
* @returns
|
||||
*/
|
||||
protected initBehaviors(optionsTable: { [key: string]: LayoutGroupOptions }) {
|
||||
const dragNodeTable: { [key: string]: boolean | string[] } = { },
|
||||
selectNodeTable: { [key: string]: boolean | string[] } = { },
|
||||
@ -152,8 +186,6 @@ import { Container } from "./container";
|
||||
});
|
||||
}
|
||||
|
||||
protected
|
||||
|
||||
protected handleChangeModels(models: Model[]) {
|
||||
const changeHighlightColor: string = this.interactionOptions.changeHighlight;
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ export class ViewManager {
|
||||
private freedContainer: Container;
|
||||
private leakContainer: Container;
|
||||
|
||||
private prevLayoutGroupTable: LayoutGroupTable;
|
||||
private prevModelList: Model[];
|
||||
|
||||
private shadowG6Instance;
|
||||
|
||||
@ -27,7 +27,7 @@ export class ViewManager {
|
||||
this.engine = engine;
|
||||
this.layouter = new Layouter(engine);
|
||||
this.mainContainer = new MainContainer(engine, DOMContainer, { tooltip: true });
|
||||
this.prevLayoutGroupTable = null;
|
||||
this.prevModelList = [];
|
||||
|
||||
const options: EngineOptions = this.engine.engineOptions;
|
||||
|
||||
@ -48,21 +48,11 @@ export class ViewManager {
|
||||
* 对每一个 model 在离屏 Canvas 上构建 G6 item,用作布局
|
||||
* @param constructList
|
||||
*/
|
||||
private build(layoutGroupTable: LayoutGroupTable) {
|
||||
layoutGroupTable.forEach(group => {
|
||||
group.element.map(item => item.cloneProps()).forEach(item => this.shadowG6Instance.addItem('node', item));
|
||||
group.pointer.map(item => item.cloneProps()).forEach(item => this.shadowG6Instance.addItem('node', item));
|
||||
group.link.map(item => item.cloneProps()).forEach(item => this.shadowG6Instance.addItem('edge', item));
|
||||
|
||||
group.element.forEach(item => {
|
||||
item.shadowG6Item = this.shadowG6Instance.findById(item.id);
|
||||
});
|
||||
group.pointer.forEach(item => {
|
||||
item.shadowG6Item = this.shadowG6Instance.findById(item.id);
|
||||
});
|
||||
group.link.forEach(item => {
|
||||
item.shadowG6Item = this.shadowG6Instance.findById(item.id);
|
||||
});
|
||||
private build(modelList: Model[]) {
|
||||
modelList.forEach(item => {
|
||||
const type = item instanceof Link? 'edge': 'node';
|
||||
this.shadowG6Instance.addItem(type, item.cloneProps());
|
||||
item.shadowG6Item = this.shadowG6Instance.findById(item.id);
|
||||
});
|
||||
}
|
||||
|
||||
@ -71,7 +61,7 @@ export class ViewManager {
|
||||
* @param layoutGroupTable
|
||||
* @returns
|
||||
*/
|
||||
private getFreedConstructList(layoutGroupTable: LayoutGroupTable): Model[] {
|
||||
private getFreedModelList(layoutGroupTable: LayoutGroupTable): Model[] {
|
||||
let freedList: Model[] = [],
|
||||
freedGroup: LayoutGroup = null,
|
||||
freedGroupName: string = null,
|
||||
@ -104,29 +94,15 @@ export class ViewManager {
|
||||
|
||||
/**
|
||||
* 获取被泄露的节点
|
||||
* @param constructList
|
||||
* @param prevConstructList
|
||||
* @param prevModelList
|
||||
* @param modelList
|
||||
* @returns
|
||||
*/
|
||||
private getLeakConstructList(prevLayoutGroupTable: LayoutGroupTable, layoutGroupTable: LayoutGroupTable): LayoutGroupTable {
|
||||
const leakLayoutGroupTable = new Map<string, LayoutGroup>();
|
||||
|
||||
prevLayoutGroupTable.forEach((item, groupName) => {
|
||||
let prevGroup = item,
|
||||
curGroup = layoutGroupTable.get(groupName),
|
||||
elements: Element[] = [],
|
||||
links: Link[] = [],
|
||||
elementIds: string[] = [];
|
||||
|
||||
if(curGroup) {
|
||||
elements = prevGroup.element.filter(item => !curGroup.element.find(n => n.id === item.id)).filter(item => item.freed === false),
|
||||
links = prevGroup.link.filter(item => !curGroup.link.find(n => n.id === item.id));
|
||||
elements = curGroup.layouter.defineLeakRule(elements);
|
||||
}
|
||||
else {
|
||||
elements = prevGroup.element;
|
||||
links = prevGroup.link;
|
||||
}
|
||||
private getLeakModelList(prevModelList: Model[], modelList: Model[]): Model[] {
|
||||
const leakModelList: Model[] = prevModelList.filter(item => !modelList.find(n => n.id === item.id)),
|
||||
elements: Element[] = <Element[]>leakModelList.filter(item => item instanceof Element && item.freed === false),
|
||||
links: Link[] = <Link[]>leakModelList.filter(item => item instanceof Link),
|
||||
elementIds: string[] = [];
|
||||
|
||||
elements.forEach(item => {
|
||||
elementIds.push(item.id);
|
||||
@ -134,32 +110,22 @@ export class ViewManager {
|
||||
fill: '#ccc'
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
for(let i = 0; i < links.length; i++) {
|
||||
let sourceId = links[i].element.id,
|
||||
targetId = links[i].target.id;
|
||||
|
||||
|
||||
links[i].set('style', {
|
||||
stroke: '#333'
|
||||
});
|
||||
|
||||
|
||||
if(elementIds.find(item => item === sourceId) === undefined || elementIds.find(item => item === targetId) === undefined) {
|
||||
links.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
leakLayoutGroupTable.set(groupName, {
|
||||
element: elements,
|
||||
link: links,
|
||||
pointer: [],
|
||||
layouter: prevGroup.layouter,
|
||||
options: prevGroup.options,
|
||||
modelList: [...elements, ...links]
|
||||
});
|
||||
});
|
||||
|
||||
return leakLayoutGroupTable;
|
||||
return [...elements, ...links];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
@ -216,17 +182,19 @@ export class ViewManager {
|
||||
renderAll(layoutGroupTable: LayoutGroupTable) {
|
||||
this.shadowG6Instance.clear();
|
||||
|
||||
this.build(layoutGroupTable);
|
||||
const modelList = Util.convertGroupTable2ModelList(layoutGroupTable);
|
||||
|
||||
let freedList = this.getFreedConstructList(layoutGroupTable),
|
||||
leakLayoutGroupTable = null;
|
||||
this.build(modelList);
|
||||
|
||||
let freedList = this.getFreedModelList(layoutGroupTable),
|
||||
leakModelList = null;
|
||||
|
||||
if(this.leakContainer && this.prevLayoutGroupTable) {
|
||||
leakLayoutGroupTable = this.getLeakConstructList(this.prevLayoutGroupTable, layoutGroupTable);
|
||||
this.build(leakLayoutGroupTable);
|
||||
if(this.leakContainer) {
|
||||
leakModelList = this.getLeakModelList(this.prevModelList, modelList);
|
||||
this.build(leakModelList);
|
||||
}
|
||||
|
||||
if(this.freedContainer) {
|
||||
if(this.freedContainer && freedList.length) {
|
||||
EventBus.emit('onFreed', freedList);
|
||||
this.freedContainer.render(freedList);
|
||||
}
|
||||
@ -234,17 +202,19 @@ export class ViewManager {
|
||||
// 进行布局(设置model的x,y)
|
||||
this.layouter.layoutAll(this.mainContainer, layoutGroupTable);
|
||||
|
||||
const modelList: Model[] = Util.convertGroupTable2ModelList(layoutGroupTable);
|
||||
this.mainContainer.render(modelList);
|
||||
|
||||
if(this.leakContainer && this.prevLayoutGroupTable) {
|
||||
if(this.leakContainer) {
|
||||
this.mainContainer.afterRemoveModels(() => {
|
||||
EventBus.emit('onLeak', leakLayoutGroupTable);
|
||||
this.leakContainer.render(Util.convertGroupTable2ModelList(leakLayoutGroupTable));
|
||||
this.leakContainer.render(leakModelList);
|
||||
|
||||
if(leakModelList.length) {
|
||||
EventBus.emit('onLeak', leakModelList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.prevLayoutGroupTable = layoutGroupTable;
|
||||
this.prevModelList = modelList;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -35,7 +35,7 @@ export class Engine {
|
||||
|
||||
this.animationOptions = Object.assign({
|
||||
enable: true,
|
||||
duration: 750,
|
||||
duration: 1000,
|
||||
timingFunction: 'easePolyOut'
|
||||
}, engineOptions.animation);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user