fix:修复释放节点的bug
This commit is contained in:
parent
2a9a108d1c
commit
ad9333bd3b
@ -216,43 +216,59 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
|
||||||
head: [
|
{
|
||||||
{
|
"LinkQueue": {
|
||||||
"type": "QPtr",
|
"data": [
|
||||||
"id": 140737338526359,
|
{
|
||||||
"label": "front",
|
"type": "head",
|
||||||
"front": "node#8358681150976310000",
|
"name": "Qptr",
|
||||||
"external": [
|
"id": 6385328,
|
||||||
"lq"
|
"label": "front",
|
||||||
]
|
"front": "node#6385360",
|
||||||
},
|
"external": [
|
||||||
{
|
"lq"
|
||||||
"type": "QPtr",
|
]
|
||||||
"id": 140737338526360,
|
},
|
||||||
"label": "rear",
|
{
|
||||||
"rear": "node#15844482482171916",
|
"type": "head",
|
||||||
"external": null
|
"name": "Qptr",
|
||||||
}
|
"id": 6385329,
|
||||||
],
|
"label": "rear",
|
||||||
node: []
|
"rear": "node#6385424",
|
||||||
|
"external": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6385360,
|
||||||
|
"data": "",
|
||||||
|
"next": "node#6385424",
|
||||||
|
"type": "node"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6385424,
|
||||||
|
"data": "F",
|
||||||
|
"next": null,
|
||||||
|
"type": "node"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6385392,
|
||||||
|
"data": "",
|
||||||
|
"next": "node#6311952",
|
||||||
|
"freed": true,
|
||||||
|
"external": [
|
||||||
|
"p"
|
||||||
|
],
|
||||||
|
"type": "node"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6311952,
|
||||||
|
"data": "1",
|
||||||
|
"next": null,
|
||||||
|
"type": "node"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"layouter": "LinkQueue"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let d = [
|
|
||||||
{ id: 10, type: 'head', name: 'QPtr', label: 'front', external: ['lq'], front: 0 },
|
|
||||||
{ id: 11, type: 'head', name: 'QPtr', label: 'rear', external: null, rear: 2 },
|
|
||||||
{ id: 0, next: 1 },
|
|
||||||
{ id: 1, next: 2 },
|
|
||||||
{ id: 2 }
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const LQueue = function(container) {
|
|
||||||
return{
|
|
||||||
engine: new LinkQueue(container),
|
|
||||||
data: [data]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
2
dist/sv.js
vendored
2
dist/sv.js
vendored
File diff suppressed because one or more lines are too long
@ -40,25 +40,15 @@ export class ModelConstructor {
|
|||||||
|
|
||||||
Object.keys(sources).forEach(name => {
|
Object.keys(sources).forEach(name => {
|
||||||
let sourceGroup = sources[name],
|
let sourceGroup = sources[name],
|
||||||
layouterName = sourceGroup.layouter;
|
layouterName = sourceGroup.layouter,
|
||||||
|
layouter: Layouter = layouterMap[sourceGroup.layouter];
|
||||||
if(!layouterName) {
|
|
||||||
layoutGroupTable.set(name, {
|
|
||||||
element: [],
|
|
||||||
link: [],
|
|
||||||
pointer: [],
|
|
||||||
options: null,
|
|
||||||
layouter: null,
|
|
||||||
modelList: []
|
|
||||||
});
|
|
||||||
|
|
||||||
|
if(!layouterName || !layouter) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sourceDataString: string = JSON.stringify(sourceGroup.data),
|
let sourceDataString: string = JSON.stringify(sourceGroup.data),
|
||||||
prevString: string = this.prevSourcesStringMap[name],
|
prevString: string = this.prevSourcesStringMap[name],
|
||||||
layouter: Layouter = null,
|
|
||||||
options: LayoutGroupOptions = null,
|
|
||||||
elementList: Element[] = [],
|
elementList: Element[] = [],
|
||||||
pointerList: Pointer[] = [];
|
pointerList: Pointer[] = [];
|
||||||
|
|
||||||
@ -66,13 +56,14 @@ export class ModelConstructor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
layouter = layouterMap[sourceGroup.layouter];
|
const options: LayoutGroupOptions = optionsTable[layouterName],
|
||||||
options = optionsTable[layouterName];
|
elementOptions = options.element || { },
|
||||||
|
pointerOptions = options.pointer || { };
|
||||||
|
|
||||||
const sourceData = layouter.sourcesPreprocess? layouter.sourcesPreprocess(sourceGroup.data): sourceGroup.data;
|
const sourceData = layouter.sourcesPreprocess? layouter.sourcesPreprocess(sourceGroup.data): sourceGroup.data;
|
||||||
|
|
||||||
elementList = this.constructElements(options.element, name, sourceData, layouterName);
|
elementList = this.constructElements(elementOptions, name, sourceData, layouterName);
|
||||||
pointerList = this.constructPointers(options.pointer, elementList);
|
pointerList = this.constructPointers(pointerOptions, elementList);
|
||||||
|
|
||||||
layoutGroupTable.set(name, {
|
layoutGroupTable.set(name, {
|
||||||
element: elementList,
|
element: elementList,
|
||||||
@ -85,7 +76,8 @@ export class ModelConstructor {
|
|||||||
});
|
});
|
||||||
|
|
||||||
layoutGroupTable.forEach((layoutGroup: LayoutGroup) => {
|
layoutGroupTable.forEach((layoutGroup: LayoutGroup) => {
|
||||||
const linkList: Link[] = this.constructLinks(layoutGroup.options.link, layoutGroup.element, layoutGroupTable);
|
const linkOptions = layoutGroup.options.link || { },
|
||||||
|
linkList: Link[] = this.constructLinks(linkOptions, layoutGroup.element, layoutGroupTable);
|
||||||
|
|
||||||
layoutGroup.link = linkList;
|
layoutGroup.link = linkList;
|
||||||
layoutGroup.modelList.push(...linkList);
|
layoutGroup.modelList.push(...linkList);
|
||||||
|
@ -201,7 +201,7 @@ export class Element extends Model {
|
|||||||
rotation: option.rotation || 0,
|
rotation: option.rotation || 0,
|
||||||
type: option.type,
|
type: option.type,
|
||||||
size: option.size,
|
size: option.size,
|
||||||
anchorPoints: option.anchorPoint,
|
anchorPoints: option.anchorPoints,
|
||||||
label: option.label,
|
label: option.label,
|
||||||
style: Util.objectClone<Style>(option.style),
|
style: Util.objectClone<Style>(option.style),
|
||||||
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
||||||
@ -279,7 +279,7 @@ export class Pointer extends Model {
|
|||||||
rotation: 0,
|
rotation: 0,
|
||||||
type: option.type || 'external-pointer',
|
type: option.type || 'external-pointer',
|
||||||
size: option.size,
|
size: option.size,
|
||||||
anchorPoints: option.anchorPoint,
|
anchorPoints: option.anchorPoints,
|
||||||
label: typeof this.label === 'string'? this.label: this.label.join(', '),
|
label: typeof this.label === 'string'? this.label: this.label.join(', '),
|
||||||
style: Util.objectClone<Style>(option.style),
|
style: Util.objectClone<Style>(option.style),
|
||||||
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
||||||
|
@ -60,7 +60,7 @@ export default G6.registerNode('binary-tree-node', {
|
|||||||
return [
|
return [
|
||||||
[0.5, 0],
|
[0.5, 0],
|
||||||
[0.125, 0.5],
|
[0.125, 0.5],
|
||||||
[0.875, 0.5],
|
[0.875, 0.5]
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
});
|
});
|
@ -8,7 +8,8 @@ export default G6.registerNode('external-pointer', {
|
|||||||
const keyShape = group.addShape('path', {
|
const keyShape = group.addShape('path', {
|
||||||
attrs: {
|
attrs: {
|
||||||
path: this.getPath(cfg),
|
path: this.getPath(cfg),
|
||||||
fill: cfg.style.fill
|
fill: cfg.style.fill,
|
||||||
|
matrix: cfg.style.matrix
|
||||||
},
|
},
|
||||||
name: 'pointer-path'
|
name: 'pointer-path'
|
||||||
});
|
});
|
||||||
|
@ -7,7 +7,7 @@ export default G6.registerNode('link-list-node', {
|
|||||||
|
|
||||||
const width = cfg.size[0],
|
const width = cfg.size[0],
|
||||||
height = cfg.size[1];
|
height = cfg.size[1];
|
||||||
|
|
||||||
const wrapperRect = group.addShape('rect', {
|
const wrapperRect = group.addShape('rect', {
|
||||||
attrs: {
|
attrs: {
|
||||||
x: width / 2,
|
x: width / 2,
|
||||||
@ -57,12 +57,12 @@ export default G6.registerNode('link-list-node', {
|
|||||||
|
|
||||||
getAnchorPoints() {
|
getAnchorPoints() {
|
||||||
return [
|
return [
|
||||||
[0, 0.5],
|
|
||||||
[5 / 6, 0.5],
|
|
||||||
[5 / 6, 0],
|
|
||||||
[5 / 6, 1],
|
|
||||||
[0.5, 0],
|
[0.5, 0],
|
||||||
[0.5, 1]
|
[5 / 6, 0],
|
||||||
|
[5 / 6, 0.5],
|
||||||
|
[5 / 6, 1],
|
||||||
|
[0.5, 1],
|
||||||
|
[0, 0.5]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -8,39 +8,54 @@ import binaryTreeNode from "./RegisteredShape/binaryTreeNode";
|
|||||||
import twoCellNode from "./RegisteredShape/twoCellNode";
|
import twoCellNode from "./RegisteredShape/twoCellNode";
|
||||||
import { Vector } from "./Common/vector";
|
import { Vector } from "./Common/vector";
|
||||||
import indexedNode from "./RegisteredShape/indexedNode";
|
import indexedNode from "./RegisteredShape/indexedNode";
|
||||||
|
import { EngineOptions, Layouter } from "./options";
|
||||||
|
|
||||||
|
|
||||||
|
export interface StructV {
|
||||||
|
(DOMContainer: HTMLElement, engineOptions: EngineOptions): Engine;
|
||||||
|
Group: typeof Group;
|
||||||
|
Bound: typeof Bound;
|
||||||
|
Vector: typeof Vector,
|
||||||
|
Mat3: any;
|
||||||
|
G6: any;
|
||||||
|
|
||||||
|
registeredShape: any[];
|
||||||
|
|
||||||
|
registeredLayouter: { [key: string]: Layouter },
|
||||||
|
|
||||||
|
registerShape: Function,
|
||||||
export const SV = {
|
|
||||||
Engine: Engine,
|
|
||||||
Group: Group,
|
|
||||||
Bound: Bound,
|
|
||||||
Vector: Vector,
|
|
||||||
Mat3: G6.Util.mat3,
|
|
||||||
G6,
|
|
||||||
|
|
||||||
registeredShape: [
|
|
||||||
externalPointer,
|
|
||||||
linkListNode,
|
|
||||||
binaryTreeNode,
|
|
||||||
twoCellNode,
|
|
||||||
indexedNode
|
|
||||||
],
|
|
||||||
|
|
||||||
registeredLayouter: { },
|
|
||||||
|
|
||||||
registerShape: G6.registerNode,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册一个布局器
|
* 注册一个布局器
|
||||||
* @param name
|
* @param name
|
||||||
* @param layouter
|
* @param layouter
|
||||||
*/
|
*/
|
||||||
registerLayouter(name: string, layouter) {
|
registerLayouter(name: string, layouter);
|
||||||
SV.registeredLayouter[name] = layouter;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
export const SV: StructV = function(DOMContainer: HTMLElement, engineOptions: EngineOptions = { }) {
|
||||||
|
return new Engine(DOMContainer, engineOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
SV.Group = Group;
|
||||||
|
SV.Bound = Bound;
|
||||||
|
SV.Vector = Vector;
|
||||||
|
SV.Mat3 = G6.Util.mat3;
|
||||||
|
SV.G6 = G6;
|
||||||
|
|
||||||
|
SV.registeredLayouter = {};
|
||||||
|
SV.registeredShape = [
|
||||||
|
externalPointer,
|
||||||
|
linkListNode,
|
||||||
|
binaryTreeNode,
|
||||||
|
twoCellNode,
|
||||||
|
indexedNode
|
||||||
|
];
|
||||||
|
|
||||||
|
SV.registerShape = G6.registerNode;
|
||||||
|
SV.registerLayouter = function(name: string, layouter) {
|
||||||
|
SV.registeredLayouter[name] = layouter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,8 +102,13 @@ import { Container } from "./container";
|
|||||||
dragStartY = null;
|
dragStartY = null;
|
||||||
|
|
||||||
g6Instance.on('node:dragstart', ev => {
|
g6Instance.on('node:dragstart', ev => {
|
||||||
const model = ev.item.getModel(),
|
const model = ev.item.getModel();
|
||||||
dragNode = this.engine.optionsTable[model.SVLayouter].behavior.dragNode;
|
|
||||||
|
if(model.SVModelType === 'pointer') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dragNode = this.engine.optionsTable[model.SVLayouter].behavior.dragNode;
|
||||||
|
|
||||||
if(dragNode === false) {
|
if(dragNode === false) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Bound, BoundingRect } from '../Common/boundingRect';
|
import { Bound, BoundingRect } from '../Common/boundingRect';
|
||||||
import { Group } from '../Common/group';
|
import { Group } from '../Common/group';
|
||||||
|
import { Vector } from '../Common/vector';
|
||||||
import { Engine } from '../engine';
|
import { Engine } from '../engine';
|
||||||
import { LayoutGroupTable } from '../Model/modelConstructor';
|
import { LayoutGroupTable } from '../Model/modelConstructor';
|
||||||
import { Element, Model, Pointer } from '../Model/modelData';
|
import { Element, Model, Pointer } from '../Model/modelData';
|
||||||
@ -41,12 +42,24 @@ export class Layouter {
|
|||||||
anchor = options.anchor || 0;
|
anchor = options.anchor || 0;
|
||||||
|
|
||||||
let target = item.target,
|
let target = item.target,
|
||||||
targetBound: BoundingRect = item.target.getBound(),
|
targetBound: BoundingRect = target.getBound(),
|
||||||
anchorPosition = item.target.G6Item.getAnchorPoints()[anchor];
|
anchorPosition = item.target.G6Item.getAnchorPoints()[anchor],
|
||||||
|
center: [number, number] = [targetBound.x + targetBound.width / 2, targetBound.y + targetBound.height / 2],
|
||||||
|
pointerPosition: [number, number];
|
||||||
|
|
||||||
|
anchorPosition = [anchorPosition.x, anchorPosition.y];
|
||||||
|
|
||||||
|
let anchorVector = Vector.subtract(anchorPosition, center),
|
||||||
|
angle = anchorVector[0] === 0? 0: (Math.PI / 2 - Math.atan(anchorVector[1] / anchorVector[0])),
|
||||||
|
len = Vector.length(anchorVector) + offset;
|
||||||
|
|
||||||
|
anchorVector = Vector.normalize(anchorVector);
|
||||||
|
pointerPosition = Vector.location(center, anchorVector, len);
|
||||||
|
|
||||||
item.set({
|
item.set({
|
||||||
x: targetBound.x + targetBound.width / 2,
|
x: pointerPosition[0],
|
||||||
y: targetBound.y - offset
|
y: pointerPosition[1],
|
||||||
|
rotation: angle
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -56,7 +69,7 @@ export class Layouter {
|
|||||||
* @param container
|
* @param container
|
||||||
* @param models
|
* @param models
|
||||||
*/
|
*/
|
||||||
private fitCenter(container: Container, group: Group) {
|
private fitCenter(container: Container, group: Group) {
|
||||||
let width = container.getG6Instance().getWidth(),
|
let width = container.getG6Instance().getWidth(),
|
||||||
height = container.getG6Instance().getHeight(),
|
height = container.getG6Instance().getHeight(),
|
||||||
viewBound: BoundingRect = group.getBound(),
|
viewBound: BoundingRect = group.getBound(),
|
||||||
@ -151,7 +164,7 @@ export class Layouter {
|
|||||||
* @param container
|
* @param container
|
||||||
* @param layoutGroupTable
|
* @param layoutGroupTable
|
||||||
*/
|
*/
|
||||||
public layoutAll(container: Container, layoutGroupTable: LayoutGroupTable) {
|
public layoutAll(container: Container, layoutGroupTable: LayoutGroupTable) {
|
||||||
layoutGroupTable.forEach(item => {
|
layoutGroupTable.forEach(item => {
|
||||||
item.modelList.forEach(model => {
|
item.modelList.forEach(model => {
|
||||||
model.G6Item = model.shadowG6Item;
|
model.G6Item = model.shadowG6Item;
|
||||||
|
@ -72,24 +72,30 @@ export class ViewManager {
|
|||||||
*/
|
*/
|
||||||
private getFreedConstructList(layoutGroupTable: LayoutGroupTable): Model[] {
|
private getFreedConstructList(layoutGroupTable: LayoutGroupTable): Model[] {
|
||||||
let freedList: Model[] = [],
|
let freedList: Model[] = [],
|
||||||
freedGroup = null,
|
freedGroup: LayoutGroup = null,
|
||||||
freedGroupName = null;
|
freedGroupName: string = null,
|
||||||
|
removeModels: Model[] = [];
|
||||||
|
|
||||||
for(let group in layoutGroupTable) {
|
layoutGroupTable.forEach((group, key) => {
|
||||||
let freedElements: Model[] = layoutGroupTable[group].element.filter(item => item.freed);
|
let freedElements: Model[] = group.element.filter(item => item.freed);
|
||||||
|
|
||||||
if(freedElements.length) {
|
if(freedElements.length) {
|
||||||
freedGroupName = group;
|
freedGroupName = key;
|
||||||
break;
|
freedList = freedElements;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
freedGroup = layoutGroupTable[freedGroupName];
|
freedGroup = layoutGroupTable.get(freedGroupName);
|
||||||
|
|
||||||
freedList.forEach(fItem => {
|
freedList.forEach(fItem => {
|
||||||
freedGroup.element.splice(freedGroup.element.findIndex(item => item.id === fItem.id), 1);
|
removeModels.push(...freedGroup.element.splice(freedGroup.element.findIndex(item => item.id === fItem.id), 1));
|
||||||
freedGroup.link.splice(freedGroup.link.findIndex(item => item.element.id === fItem.id || item.target.id === fItem.id));
|
removeModels.push(...freedGroup.link.splice(freedGroup.link.findIndex(item => item.element.id === fItem.id || item.target.id === fItem.id)));
|
||||||
freedGroup.pointer.splice(freedGroup.pointer.findIndex(item => item.target.id === fItem.id));
|
removeModels.push(...freedGroup.pointer.splice(freedGroup.pointer.findIndex(item => item.target.id === fItem.id)));
|
||||||
|
});
|
||||||
|
|
||||||
|
removeModels.map(model => {
|
||||||
|
const index = freedGroup.modelList.findIndex(item => item.id === model.id);
|
||||||
|
freedGroup.modelList.splice(index, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
return freedList;
|
return freedList;
|
||||||
|
@ -18,7 +18,7 @@ export class Engine {
|
|||||||
|
|
||||||
public optionsTable: { [key: string]: LayoutGroupOptions };
|
public optionsTable: { [key: string]: LayoutGroupOptions };
|
||||||
|
|
||||||
constructor(DOMContainer: HTMLElement, engineOptions: EngineOptions = { }) {
|
constructor(DOMContainer: HTMLElement, engineOptions: EngineOptions) {
|
||||||
this.optionsTable = {};
|
this.optionsTable = {};
|
||||||
|
|
||||||
this.engineOptions = Object.assign({
|
this.engineOptions = Object.assign({
|
||||||
|
@ -36,7 +36,7 @@ export interface ElementOption {
|
|||||||
type: string;
|
type: string;
|
||||||
size: number | [number, number];
|
size: number | [number, number];
|
||||||
rotation: number;
|
rotation: number;
|
||||||
anchorPoint: [number, number];
|
anchorPoints: [number, number];
|
||||||
label: string;
|
label: string;
|
||||||
labelOptions: ElementLabelOption;
|
labelOptions: ElementLabelOption;
|
||||||
style: Style;
|
style: Style;
|
||||||
|
Loading…
Reference in New Issue
Block a user