fix: 修复freed面板的一些bug

This commit is contained in:
黎智洲 2021-08-17 23:44:28 +08:00
parent 07358a4038
commit 374bff38ff
9 changed files with 168 additions and 147 deletions

View File

@ -105,6 +105,8 @@ SV.registerLayouter('GeneralizedList', {
} }
}, },
link: { link: {
loopSub: {},
loopNext: {},
sub: { sub: {
type: 'line', type: 'line',
sourceAnchor: 2, sourceAnchor: 2,

View File

@ -18,7 +18,7 @@ SV.registerLayouter('LinkList', {
element: { element: {
default: { default: {
type: 'link-list-node', type: 'link-list-node',
label: '[id]', label: '[data]',
size: [60, 30], size: [60, 30],
style: { style: {
stroke: '#333', stroke: '#333',

View File

@ -32,18 +32,27 @@ SV.registerLayouter('Stack', {
} }
} }
}, },
pointer: { marker: {
external: { external: {
type: 'pointer',
anchor: 1, anchor: 1,
style: { style: {
fill: '#f08a5d' fill: '#f08a5d'
} }
}, },
bottomExternal: { bottomExternal: {
type: 'pointer',
anchor: 2, anchor: 2,
style: { style: {
fill: '#f08a5d' fill: '#f08a5d'
} }
},
cursor: {
type: 'cursor',
anchor: 1,
style: {
fill: '#f08a5d'
}
} }
}, },
layout: { layout: {

View File

@ -80,92 +80,30 @@
let cur = SV(document.getElementById('container'), { let cur = SV(document.getElementById('container'), {
freedContainer: document.getElementById('freed'), freedContainer: document.getElementById('freed'),
leakContainer: document.getElementById('leak') leakContainer: document.getElementById('leak'),
view: {
groupPadding: 40,
},
}); });
let data = [{ let data = [{
"LinkQueue": { "LinkStack0": {
"data": [ "data": [
{ { id: 6, next: 7 },
"type": "head", { id: 7, next: 8 },
"name": "Qptr", { id: 8, external: 'h', data: '66' }
"id": "0x616eb0",
"label": "front",
"front": "node#0x616ed0",
"external": [
"lq"
]
},
{
"type": "head",
"name": "Qptr",
"id": "0x616eb1",
"label": "rear",
"rear": "node#0x616ed0",
"external": null
},
{
"type": "node",
"id": "0x616ed0",
"data": "",
"next": null,
"root": true
},
{
"type": "node",
"id": "0x616ef0",
"data": "D",
"next": null,
"root": true,
"external": [
"p"
]
}
], ],
"layouter": "LinkQueue" "layouter": "LinkList"
} }
}, { }, {
"LinkQueue": { "LinkStack0": {
"data": [ "data": [
{ { id: 6, next: 7 },
"type": "head", { id: 7, next: 8 },
"name": "Qptr", { id: 8, freed: true, external: 'h' }
"id": "0x616eb0",
"label": "front",
"front": "node#0x616ed0",
"external": [
"lq"
]
},
{
"type": "head",
"name": "Qptr",
"id": "0x616eb1",
"label": "rear",
"rear": "node#0x616ed0",
"external": null
},
{
"type": "node",
"id": "0x616ed0",
"data": "",
"next": null,
"root": true
},
{
"type": "node",
"id": "0x616ef0",
"data": "",
"next": null,
"root": true,
"external": [
"p"
], ],
"freed": true "layouter": "LinkList"
}
],
"layouter": "LinkQueue"
} }
}]; }];

2
dist/sv.js vendored

File diff suppressed because one or more lines are too long

View File

@ -7,6 +7,7 @@ import { Element, Link, Marker, Model } from "./modelData";
export type LayoutGroup = { export type LayoutGroup = {
name: string;
element: Element[]; element: Element[];
link: Link[]; link: Link[];
marker: Marker[]; marker: Marker[];
@ -64,9 +65,10 @@ export class ModelConstructor {
markerOptions = options.marker || { }; markerOptions = options.marker || { };
elementList = this.constructElements(elementOptions, name, sourceData, layouterName); elementList = this.constructElements(elementOptions, name, sourceData, layouterName);
markerList = this.constructMarkers(markerOptions, elementList); markerList = this.constructMarkers(name, markerOptions, elementList);
layoutGroupTable.set(name, { layoutGroupTable.set(name, {
name,
element: elementList, element: elementList,
link: [], link: [],
marker: markerList, marker: markerList,
@ -186,7 +188,7 @@ export class ModelConstructor {
* @param elements * @param elements
* @returns * @returns
*/ */
private constructMarkers(markerOptions: { [key: string]: MarkerOption }, elements: Element[]): Marker[] { private constructMarkers(groupName: string, markerOptions: { [key: string]: MarkerOption }, elements: Element[]): Marker[] {
let markerList: Marker[] = [], let markerList: Marker[] = [],
markerNames = Object.keys(markerOptions); markerNames = Object.keys(markerOptions);
@ -198,7 +200,7 @@ export class ModelConstructor {
// 若没有指针字段的结点则跳过 // 若没有指针字段的结点则跳过
if(!markerData) continue; if(!markerData) continue;
let id = name + '.' + (Array.isArray(markerData)? markerData.join('-'): markerData), let id = `${groupName}.${name}.${Array.isArray(markerData)? markerData.join('-'): markerData}`,
marker = this.createMarker(id, name, markerData, element, markerOptions[name]); marker = this.createMarker(id, name, markerData, element, markerOptions[name]);
markerList.push(marker); markerList.push(marker);

View File

@ -174,6 +174,47 @@ export class Layouter {
return wrapperGroup; return wrapperGroup;
} }
public layoutSingleMarker(marker: Marker, markerOptions: { [key: string]: MarkerOption }) {
const options: MarkerOption = markerOptions[marker.getType()],
offset = options.offset ?? 8,
anchor = marker.anchor ?? 0,
labelOffset = options.labelOffset ?? 2;
let target = marker.target,
targetBound: BoundingRect = target.getBound(),
anchorPosition = marker.target.G6Item.getAnchorPoints()[anchor],
center: [number, number] = [targetBound.x + targetBound.width / 2, targetBound.y + targetBound.height / 2],
markerPosition: [number, number],
markerEndPosition: [number, number];
anchorPosition = [anchorPosition.x, anchorPosition.y];
let anchorVector = Vector.subtract(anchorPosition, center),
angle = 0, len = Vector.length(anchorVector) + offset;
if (anchorVector[0] === 0) {
angle = anchorVector[1] > 0 ? -Math.PI : 0;
}
else {
angle = Math.sign(anchorVector[0]) * (Math.PI / 2 - Math.atan(anchorVector[1] / anchorVector[0]));
}
const markerHeight = marker.get('size')[1],
labelRadius = marker.getLabelSizeRadius() / 2;
anchorVector = Vector.normalize(anchorVector);
markerPosition = Vector.location(center, anchorVector, len);
markerEndPosition = Vector.location(center, anchorVector, markerHeight + len + labelRadius + labelOffset);
markerEndPosition = Vector.subtract(markerEndPosition, markerPosition);
marker.set({
x: markerPosition[0],
y: markerPosition[1],
rotation: angle,
markerEndPosition
});
}
/** /**
* *
* @param container * @param container

View File

@ -1,5 +1,5 @@
import { Engine } from "../engine"; import { Engine } from "../engine";
import { Element, Link, Model } from "../Model/modelData"; import { Element, Link, Marker, Model } from "../Model/modelData";
import { EngineOptions } from "../options"; import { EngineOptions } from "../options";
import { Container } from "./container/container"; import { Container } from "./container/container";
import { SV } from '../StructV'; import { SV } from '../StructV';
@ -19,6 +19,7 @@ export class ViewManager {
private freedContainer: Container; private freedContainer: Container;
private leakContainer: Container; private leakContainer: Container;
private prevLayoutGroupTable: LayoutGroupTable;
private prevModelList: Model[]; private prevModelList: Model[];
private shadowG6Instance; private shadowG6Instance;
@ -27,6 +28,7 @@ export class ViewManager {
this.engine = engine; this.engine = engine;
this.layouter = new Layouter(engine); this.layouter = new Layouter(engine);
this.mainContainer = new MainContainer(engine, DOMContainer, { tooltip: true }); this.mainContainer = new MainContainer(engine, DOMContainer, { tooltip: true });
this.prevLayoutGroupTable = new Map();
this.prevModelList = []; this.prevModelList = [];
const options: EngineOptions = this.engine.engineOptions; const options: EngineOptions = this.engine.engineOptions;
@ -56,29 +58,50 @@ export class ViewManager {
}); });
} }
/**
*
* @param freedElement
* @param prevLayoutGroup
*/
private handleFreedLabel(freedElement: Element[], prevLayoutGroup: LayoutGroup) {
if(prevLayoutGroup === undefined) {
return;
}
const prevElementList: Element[] = prevLayoutGroup.element;
freedElement.map(item => {
let prevElement = prevElementList.find(el => el.id === item.id),
prevLabel = prevElement.get('label') ?? '';
item.set('label', prevLabel);
});
}
/** /**
* free * free
* @param layoutGroupTable * @param layoutGroupTable
* @returns * @returns
*/ */
private getFreedModelList(layoutGroupTable: LayoutGroupTable): Model[] { private getFreedModelList(prevLayoutGroupTable: LayoutGroupTable, layoutGroupTable: LayoutGroupTable): Model[] {
let freedList: Model[] = [], let freedElements: Element[] = [],
freedMarkers: Marker[] = [],
freedGroup: LayoutGroup = null, freedGroup: LayoutGroup = null,
freedGroupName: string = null, freedGroupName: string = null,
removeModels: Model[] = []; removeModels: Model[] = [];
layoutGroupTable.forEach((group, key) => { layoutGroupTable.forEach((group, key) => {
let freedElements: Element[] = group.element.filter(item => item.freed); let targetElements: Element[] = group.element.filter(item => item.freed);
if(freedElements.length) { if (targetElements.length) {
freedGroupName = key; freedGroupName = key;
freedList = freedElements; freedElements = targetElements;
} }
}); });
freedGroup = layoutGroupTable.get(freedGroupName); freedGroup = layoutGroupTable.get(freedGroupName);
freedList.forEach(fItem => { freedElements.forEach(fItem => {
removeModels.push( removeModels.push(
...Util.removeFromList(freedGroup.element, item => item.id === fItem.id), ...Util.removeFromList(freedGroup.element, item => item.id === fItem.id),
...Util.removeFromList(freedGroup.link, item => item.element.id === fItem.id || item.target.id === fItem.id), ...Util.removeFromList(freedGroup.link, item => item.element.id === fItem.id || item.target.id === fItem.id),
@ -90,7 +113,14 @@ export class ViewManager {
Util.removeFromList(freedGroup.modelList, item => item.id === model.id); Util.removeFromList(freedGroup.modelList, item => item.id === model.id);
}); });
return freedList; freedElements.map(item => {
const markers = Object.keys(item.markers).map(name => item.markers[name]);
freedMarkers.push(...markers);
});
this.handleFreedLabel(freedElements, prevLayoutGroupTable.get(freedGroupName));
return [...freedElements, ...freedMarkers];
} }
/** /**
@ -191,35 +221,33 @@ export class ViewManager {
renderAll(layoutGroupTable: LayoutGroupTable) { renderAll(layoutGroupTable: LayoutGroupTable) {
this.shadowG6Instance.clear(); this.shadowG6Instance.clear();
let modelList = Util.convertGroupTable2ModelList(layoutGroupTable); let modelList = Util.convertGroupTable2ModelList(layoutGroupTable),
leakModelList = [],
freedList = [];
this.build(modelList); this.build(modelList);
let freedList = this.getFreedModelList(layoutGroupTable),
leakModelList = null;
if (this.leakContainer) { if (this.leakContainer) {
leakModelList = this.getLeakModelList(this.prevModelList, modelList); leakModelList = this.getLeakModelList(this.prevModelList, modelList);
this.build(leakModelList); this.build(leakModelList);
} }
// 进行布局设置model的xy
this.layouter.layoutAll(this.mainContainer, layoutGroupTable);
freedList = this.getFreedModelList(this.prevLayoutGroupTable, layoutGroupTable);
if (this.freedContainer && freedList.length) { if (this.freedContainer && freedList.length) {
EventBus.emit('onFreed', freedList); EventBus.emit('onFreed', freedList);
this.freedContainer.render(freedList); this.freedContainer.render(freedList);
} }
// 进行布局设置model的xy
this.layouter.layoutAll(this.mainContainer, layoutGroupTable);
// 从新获取一次因为第一次获取没有把freed节点筛选出去 // 从新获取一次因为第一次获取没有把freed节点筛选出去
modelList = Util.convertGroupTable2ModelList(layoutGroupTable); modelList = Util.convertGroupTable2ModelList(layoutGroupTable);
this.mainContainer.render(modelList); this.mainContainer.render(modelList);
if (this.leakContainer) { if (this.leakContainer) {
this.mainContainer.afterRemoveModels(() => { this.mainContainer.afterRemoveModels(() => {});
});
this.leakContainer.render(leakModelList); this.leakContainer.render(leakModelList);
if (leakModelList.length) { if (leakModelList.length) {
@ -227,6 +255,7 @@ export class ViewManager {
} }
} }
this.prevLayoutGroupTable = layoutGroupTable;
this.prevModelList = modelList; this.prevModelList = modelList;
} }