bug修复
This commit is contained in:
parent
0dcad0f117
commit
a623ae7445
@ -17,6 +17,14 @@ class Arrays extends Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
pointer: {
|
||||||
|
external: {
|
||||||
|
offset: 8,
|
||||||
|
style: {
|
||||||
|
fill: '#f08a5d'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
interaction: {
|
interaction: {
|
||||||
dragNode: false
|
dragNode: false
|
||||||
}
|
}
|
||||||
@ -41,7 +49,7 @@ const A = function(container) {
|
|||||||
return{
|
return{
|
||||||
engine: new Arrays(container),
|
engine: new Arrays(container),
|
||||||
data: [[
|
data: [[
|
||||||
{ id: 1 },
|
{ id: 1, external: 'A' },
|
||||||
{ id: 2 },
|
{ id: 2 },
|
||||||
{ id: 3 },
|
{ id: 3 },
|
||||||
{ id: 4 },
|
{ id: 4 },
|
||||||
@ -56,7 +64,7 @@ const A = function(container) {
|
|||||||
{ id: 1 },
|
{ id: 1 },
|
||||||
{ id: 2 },
|
{ id: 2 },
|
||||||
{ id: 3 },
|
{ id: 3 },
|
||||||
{ id: 6 },
|
{ id: 6, external: 'A' },
|
||||||
{ id: 7 },
|
{ id: 7 },
|
||||||
{ id: 8 }
|
{ id: 8 }
|
||||||
]]
|
]]
|
||||||
|
|||||||
@ -164,27 +164,66 @@ class BinaryTree extends Engine {
|
|||||||
const BTree = function(container) {
|
const BTree = function(container) {
|
||||||
return{
|
return{
|
||||||
engine: new BinaryTree(container),
|
engine: new BinaryTree(container),
|
||||||
data: [[
|
data: [
|
||||||
{ id: 1, child: [2, 3], root: true, external: ['treeA', 'gear'] },
|
// [
|
||||||
{ id: 2, child: [null, 6] },
|
// { id: 1, child: [2, 3], root: true, external: ['treeA', 'gear'] },
|
||||||
{ id: 3, child: [5, 4] },
|
// { id: 2, child: [null, 6] },
|
||||||
{ id: 4, external: 'foo' },
|
// { id: 3, child: [5, 4] },
|
||||||
{ id: 5 },
|
// { id: 4, external: 'foo' },
|
||||||
{ id: 6, external: 'bar', child: [null, 7] },
|
// { id: 5 },
|
||||||
{ id: 7 },
|
// { id: 6, external: 'bar', child: [null, 7] },
|
||||||
{ id: 8, child: [9, 10], root: true },
|
// { id: 7 },
|
||||||
{ id: 9, child: [11, null] },
|
// { id: 8, child: [9, 10], root: true },
|
||||||
{ id: 10 },
|
// { id: 9, child: [11, null] },
|
||||||
{ id: 11 }
|
// { id: 10 },
|
||||||
],
|
// { id: 11 }
|
||||||
|
// ],
|
||||||
|
// [
|
||||||
|
// { id: 1, child: [2, 3], root: true, external: 'treeA' },
|
||||||
|
// { id: 2, external: 'gear' },
|
||||||
|
// { id: 3, child: [5, 4] },
|
||||||
|
// { id: 4, external: 'foo' },
|
||||||
|
// { id: 5, child: [12, 13] },
|
||||||
|
// { id: 12 }, { id: 13 }
|
||||||
|
// ]
|
||||||
[
|
[
|
||||||
{ id: 1, child: [2, 3], root: true, external: 'treeA' },
|
{
|
||||||
{ id: 2, external: 'gear' },
|
"external": [
|
||||||
{ id: 3, child: [5, 4] },
|
"r",
|
||||||
{ id: 4, external: 'foo' },
|
"T1"
|
||||||
{ id: 5, child: [12, 13] },
|
],
|
||||||
{ id: 12 }, { id: 13 }
|
"child": [
|
||||||
]]
|
6385376,
|
||||||
|
6385424
|
||||||
|
],
|
||||||
|
"id": 6385328,
|
||||||
|
"name": "T1",
|
||||||
|
"data": "Z",
|
||||||
|
"root": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"child": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"id": 6385376,
|
||||||
|
"name": "T1.lchild",
|
||||||
|
"data": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"external": [
|
||||||
|
"t"
|
||||||
|
],
|
||||||
|
"child": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"id": 6385424,
|
||||||
|
"name": "T1.rchild",
|
||||||
|
"data": "B"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
162
demo/dataStruct/ChainHashTable.js
Normal file
162
demo/dataStruct/ChainHashTable.js
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连地址哈希表
|
||||||
|
*/
|
||||||
|
class ChainHashTable extends Engine {
|
||||||
|
|
||||||
|
defineOptions() {
|
||||||
|
return {
|
||||||
|
element: {
|
||||||
|
head: {
|
||||||
|
type: 'two-cell-node',
|
||||||
|
label: '[id]',
|
||||||
|
size: [70, 40],
|
||||||
|
style: {
|
||||||
|
stroke: '#333',
|
||||||
|
fill: '#b83b5e'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
type: 'link-list-node',
|
||||||
|
label: '[id]',
|
||||||
|
size: [60, 30],
|
||||||
|
style: {
|
||||||
|
stroke: '#333',
|
||||||
|
fill: '#b83b5e'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
start: {
|
||||||
|
type: 'line',
|
||||||
|
sourceAnchor: 1,
|
||||||
|
targetAnchor: 0,
|
||||||
|
style: {
|
||||||
|
stroke: '#333',
|
||||||
|
endArrow: {
|
||||||
|
path: G6.Arrow.triangle(8, 6, 0),
|
||||||
|
fill: '#333'
|
||||||
|
},
|
||||||
|
startArrow: {
|
||||||
|
path: G6.Arrow.circle(2, -1),
|
||||||
|
fill: '#333'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
next: {
|
||||||
|
type: 'line',
|
||||||
|
sourceAnchor: 1,
|
||||||
|
targetAnchor: 0,
|
||||||
|
style: {
|
||||||
|
stroke: '#333',
|
||||||
|
endArrow: {
|
||||||
|
path: G6.Arrow.triangle(8, 6, 0),
|
||||||
|
fill: '#333'
|
||||||
|
},
|
||||||
|
startArrow: {
|
||||||
|
path: G6.Arrow.circle(2, -1),
|
||||||
|
fill: '#333'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
external: {
|
||||||
|
offset: 8,
|
||||||
|
style: {
|
||||||
|
fill: '#f08a5d'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
xInterval: 50,
|
||||||
|
yInterval: 50
|
||||||
|
},
|
||||||
|
interaction: {
|
||||||
|
dragNode: ['node']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对子树进行递归布局
|
||||||
|
* @param node
|
||||||
|
* @param parent
|
||||||
|
*/
|
||||||
|
layoutItem(node, prev, layoutOptions) {
|
||||||
|
if(!node) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let width = node.get('size')[0];
|
||||||
|
|
||||||
|
if(prev) {
|
||||||
|
node.set('y', prev.get('y'));
|
||||||
|
node.set('x', prev.get('x') + layoutOptions.xInterval + width);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node.next) {
|
||||||
|
this.layoutItem(node.next, node, layoutOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
layout(elements, layoutOptions) {
|
||||||
|
let headNode = elements.head;
|
||||||
|
|
||||||
|
for(let i = 0; i < headNode.length; i++) {
|
||||||
|
let node = headNode[i],
|
||||||
|
height = node.get('size')[1];
|
||||||
|
|
||||||
|
node.set('y', node.get('y') + i * height);
|
||||||
|
|
||||||
|
if(node.start) {
|
||||||
|
let y = node.get('y') + height - node.start.get('size')[1],
|
||||||
|
x = layoutOptions.xInterval * 2.5;
|
||||||
|
|
||||||
|
node.start.set({ x, y });
|
||||||
|
this.layoutItem(node.start, null, layoutOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CHT = function(container) {
|
||||||
|
return{
|
||||||
|
engine: new ChainHashTable(container),
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
head: [{
|
||||||
|
id: 0,
|
||||||
|
start: 'node#0'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
start: 'node#2'
|
||||||
|
}],
|
||||||
|
node: [{
|
||||||
|
id: 0,
|
||||||
|
next: 1
|
||||||
|
}, {
|
||||||
|
id: 1
|
||||||
|
},{
|
||||||
|
id: 2,
|
||||||
|
next: 3
|
||||||
|
}, {
|
||||||
|
id: 3
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1,26 +1,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单链表
|
* 单链表
|
||||||
*/
|
*/
|
||||||
class HashLinkList extends Engine {
|
class LinkStack extends Engine {
|
||||||
|
|
||||||
defineOptions() {
|
defineOptions() {
|
||||||
return {
|
return {
|
||||||
element: {
|
element: {
|
||||||
headNode: {
|
default: {
|
||||||
type: 'link-list-node',
|
|
||||||
label: '[id]',
|
|
||||||
size: [60, 30],
|
|
||||||
style: {
|
|
||||||
stroke: '#333',
|
|
||||||
fill: '#b83b5e'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
node: {
|
|
||||||
type: 'link-list-node',
|
type: 'link-list-node',
|
||||||
label: '[id]',
|
label: '[id]',
|
||||||
size: [60, 30],
|
size: [60, 30],
|
||||||
@ -34,7 +21,7 @@
|
|||||||
next: {
|
next: {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
sourceAnchor: 1,
|
sourceAnchor: 1,
|
||||||
targetAnchor: 0,
|
targetAnchor: 2,
|
||||||
style: {
|
style: {
|
||||||
stroke: '#333',
|
stroke: '#333',
|
||||||
endArrow: {
|
endArrow: {
|
||||||
@ -50,7 +37,7 @@
|
|||||||
},
|
},
|
||||||
pointer: {
|
pointer: {
|
||||||
external: {
|
external: {
|
||||||
offset: 14,
|
offset: 8,
|
||||||
style: {
|
style: {
|
||||||
fill: '#f08a5d'
|
fill: '#f08a5d'
|
||||||
}
|
}
|
||||||
@ -58,7 +45,7 @@
|
|||||||
},
|
},
|
||||||
layout: {
|
layout: {
|
||||||
xInterval: 50,
|
xInterval: 50,
|
||||||
yInterval: 50
|
yInterval: 30
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -74,11 +61,11 @@
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let width = node.get('size')[0];
|
let height = node.get('size')[1];
|
||||||
|
|
||||||
if(prev) {
|
if(prev) {
|
||||||
node.set('y', prev.get('y'));
|
node.set('x', prev.get('x'));
|
||||||
node.set('x', prev.get('x') + layoutOptions.xInterval + width);
|
node.set('y', prev.get('y') + layoutOptions.yInterval + height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node.next) {
|
if(node.next) {
|
||||||
@ -103,20 +90,20 @@
|
|||||||
|
|
||||||
for(i = 0; i < rootNodes.length; i++) {
|
for(i = 0; i < rootNodes.length; i++) {
|
||||||
let root = rootNodes[i],
|
let root = rootNodes[i],
|
||||||
height = root.get('size')[1];
|
width = root.get('size')[0];
|
||||||
|
|
||||||
root.set('y', root.get('y') + i * (layoutOptions.yInterval + height));
|
root.set('x', root.get('x') + i * (layoutOptions.xInterval + width));
|
||||||
this.layoutItem(root, null, layoutOptions);
|
this.layoutItem(root, null, layoutOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const LList = function(container) {
|
const LStack = function(container) {
|
||||||
return{
|
return{
|
||||||
engine: new LinkList(container),
|
engine: new LinkStack(container),
|
||||||
data: [[
|
data: [[
|
||||||
{ id: 1, root: true, next: 2, external: ['gg'] },
|
{ id: 1, root: true, next: 2 },
|
||||||
{ id: 2, next: 3 },
|
{ id: 2, next: 3 },
|
||||||
{ id: 3, next: 4 },
|
{ id: 3, next: 4 },
|
||||||
{ id: 4, next: 5 },
|
{ id: 4, next: 5 },
|
||||||
@ -128,7 +115,7 @@ const LList = function(container) {
|
|||||||
{ id: 10 }
|
{ id: 10 }
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{ id: 1, root: true, next: 2, external: ['gg'] },
|
{ id: 1, root: true, next: 2 },
|
||||||
{ id: 2, next: 3 },
|
{ id: 2, next: 3 },
|
||||||
{ id: 3, next: 6 },
|
{ id: 3, next: 6 },
|
||||||
{ id: 6, next: 7 },
|
{ id: 6, next: 7 },
|
||||||
71
demo/dataStruct/Stack.js
Normal file
71
demo/dataStruct/Stack.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class Stack extends Engine {
|
||||||
|
defineOptions() {
|
||||||
|
return {
|
||||||
|
element: {
|
||||||
|
default: {
|
||||||
|
type: 'rect',
|
||||||
|
label: '[id]',
|
||||||
|
size: [60, 30],
|
||||||
|
style: {
|
||||||
|
stroke: '#333',
|
||||||
|
fill: '#95e1d3'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
external: {
|
||||||
|
offset: 8,
|
||||||
|
style: {
|
||||||
|
fill: '#f08a5d'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
interaction: {
|
||||||
|
dragNode: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
layout(elements, layoutOptions) {
|
||||||
|
let blocks = elements.default;
|
||||||
|
|
||||||
|
for(let i = 1; i < blocks.length; i++) {
|
||||||
|
let item = blocks[i],
|
||||||
|
prev = blocks[i - 1],
|
||||||
|
height = item.get('size')[1];
|
||||||
|
|
||||||
|
item.set('y', prev.get('y') + height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const St = function(container) {
|
||||||
|
return{
|
||||||
|
engine: new Stack(container),
|
||||||
|
data: [[
|
||||||
|
{ id: 1 },
|
||||||
|
{ id: 2 },
|
||||||
|
{ id: 3 },
|
||||||
|
{ id: 4 },
|
||||||
|
{ id: 5 },
|
||||||
|
{ id: 6 },
|
||||||
|
{ id: 7 },
|
||||||
|
{ id: 8 },
|
||||||
|
{ id: 9 },
|
||||||
|
{ id: 10 }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ id: 1 },
|
||||||
|
{ id: 2 },
|
||||||
|
{ id: 3 },
|
||||||
|
{ id: 6 },
|
||||||
|
{ id: 7 },
|
||||||
|
{ id: 8 }
|
||||||
|
]]
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -37,7 +37,7 @@ class LinkList extends Engine {
|
|||||||
},
|
},
|
||||||
pointer: {
|
pointer: {
|
||||||
external: {
|
external: {
|
||||||
offset: 14,
|
offset: 8,
|
||||||
style: {
|
style: {
|
||||||
fill: '#f08a5d'
|
fill: '#f08a5d'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,13 +39,16 @@ const Engine = SV.Engine,
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script src="./dataStruct/BinaryTree.js"></script>
|
<script src="./dataStruct/BinaryTree.js"></script>
|
||||||
<script src="./dataStruct/linkList.js"></script>
|
<script src="./dataStruct/LinkList.js"></script>
|
||||||
<script src="./dataStruct/Array.js"></script>
|
<script src="./dataStruct/Array.js"></script>
|
||||||
|
<script src="./dataStruct/ChainHashTable.js"></script>
|
||||||
|
<script src="./dataStruct/Stack.js"></script>
|
||||||
|
<script src="./dataStruct/LinkStack.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
const engines = [BTree, LList, A];
|
const engines = [BTree, LList, A, CHT, St, LStack];
|
||||||
|
|
||||||
let cur = engines[2](document.getElementById('container'));
|
let cur = engines[5](document.getElementById('container'));
|
||||||
|
|
||||||
cur.engine.render(cur.data[0]);
|
cur.engine.render(cur.data[0]);
|
||||||
|
|
||||||
|
|||||||
2
dist/sv.js
vendored
2
dist/sv.js
vendored
File diff suppressed because one or more lines are too long
@ -158,7 +158,7 @@ export class ModelConstructor {
|
|||||||
// 若没有指针字段的结点则跳过
|
// 若没有指针字段的结点则跳过
|
||||||
if(!pointerData) continue;
|
if(!pointerData) continue;
|
||||||
|
|
||||||
let id = name + '#' + (Array.isArray(pointerData)? pointerData.join('-'): pointerData),
|
let id = name + '.' + (Array.isArray(pointerData)? pointerData.join('-'): pointerData),
|
||||||
pointer = this.createPointer(id, name, pointerData, element);
|
pointer = this.createPointer(id, name, pointerData, element);
|
||||||
|
|
||||||
pointerContainer[name].push(pointer);
|
pointerContainer[name].push(pointer);
|
||||||
@ -176,9 +176,14 @@ export class ModelConstructor {
|
|||||||
private createElement(sourceElement: SourceElement, elementName: string): Element {
|
private createElement(sourceElement: SourceElement, elementName: string): Element {
|
||||||
let elementOption = this.engine.elementOptions[elementName],
|
let elementOption = this.engine.elementOptions[elementName],
|
||||||
element: Element = undefined,
|
element: Element = undefined,
|
||||||
label = elementOption.label? this.parserElementContent(sourceElement, elementOption.label): '';
|
label = elementOption.label? this.parserElementContent(sourceElement, elementOption.label): '',
|
||||||
|
id = elementName + '.' + sourceElement.id.toString();
|
||||||
|
|
||||||
element = new Element(elementName, sourceElement);
|
if(label === null || label === undefined) {
|
||||||
|
label = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
element = new Element(id, elementName, sourceElement);
|
||||||
element.initProps(elementOption);
|
element.initProps(elementOption);
|
||||||
element.set('label', label);
|
element.set('label', label);
|
||||||
element.sourceElement = sourceElement;
|
element.sourceElement = sourceElement;
|
||||||
@ -251,7 +256,7 @@ export class ModelConstructor {
|
|||||||
element: Element,
|
element: Element,
|
||||||
linkTarget: LinkTarget
|
linkTarget: LinkTarget
|
||||||
): Element {
|
): Element {
|
||||||
let elementName = element.name,
|
let elementName = element.modelName,
|
||||||
elementList: Element[],
|
elementList: Element[],
|
||||||
targetId = linkTarget,
|
targetId = linkTarget,
|
||||||
targetElement = null;
|
targetElement = null;
|
||||||
@ -277,7 +282,7 @@ export class ModelConstructor {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetElement = elementList.find(item => item.id === targetId);
|
targetElement = elementList.find(item => item.sourceId === targetId);
|
||||||
return targetElement || null;
|
return targetElement || null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -17,6 +17,7 @@ export interface G6NodeModel {
|
|||||||
labelCfg: ElementLabelOption;
|
labelCfg: ElementLabelOption;
|
||||||
externalPointerId: string;
|
externalPointerId: string;
|
||||||
modelType: string;
|
modelType: string;
|
||||||
|
modelName: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -35,8 +36,8 @@ export interface G6EdgeModel {
|
|||||||
|
|
||||||
export class Model {
|
export class Model {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
modelName: string;
|
||||||
type: string;
|
modelType: string;
|
||||||
|
|
||||||
props: G6NodeModel | G6EdgeModel;
|
props: G6NodeModel | G6EdgeModel;
|
||||||
shadowG6Item;
|
shadowG6Item;
|
||||||
@ -45,7 +46,7 @@ export class Model {
|
|||||||
|
|
||||||
constructor(id: string, name: string) {
|
constructor(id: string, name: string) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.modelName = name;
|
||||||
this.shadowG6Item = null;
|
this.shadowG6Item = null;
|
||||||
this.renderG6Item = null;
|
this.renderG6Item = null;
|
||||||
this.G6Item = null;
|
this.G6Item = null;
|
||||||
@ -148,17 +149,20 @@ export class Model {
|
|||||||
|
|
||||||
|
|
||||||
export class Element extends Model {
|
export class Element extends Model {
|
||||||
type = 'element';
|
modelType = 'element';
|
||||||
sourceElement: SourceElement;
|
sourceElement: SourceElement;
|
||||||
|
sourceId: string;
|
||||||
|
|
||||||
constructor(type: string, sourceElement: SourceElement) {
|
constructor(id: string, type: string, sourceElement: SourceElement) {
|
||||||
super(sourceElement.id.toString(), type);
|
super(id, type);
|
||||||
|
|
||||||
Object.keys(sourceElement).map(prop => {
|
Object.keys(sourceElement).map(prop => {
|
||||||
if(prop !== 'id') {
|
if(prop !== 'id') {
|
||||||
this[prop] = sourceElement[prop];
|
this[prop] = sourceElement[prop];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.sourceId = this.id.split('.')[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected defineProps(option: ElementOption) {
|
protected defineProps(option: ElementOption) {
|
||||||
@ -174,7 +178,8 @@ export class Element extends Model {
|
|||||||
style: Util.objectClone<Style>(option.style),
|
style: Util.objectClone<Style>(option.style),
|
||||||
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
||||||
externalPointerId: null,
|
externalPointerId: null,
|
||||||
modelType: this.type
|
modelType: this.modelType,
|
||||||
|
modelName: this.modelName
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -182,7 +187,7 @@ export class Element extends Model {
|
|||||||
|
|
||||||
|
|
||||||
export class Link extends Model {
|
export class Link extends Model {
|
||||||
type = 'link';
|
modelType = 'link';
|
||||||
element: Element;
|
element: Element;
|
||||||
target: Element;
|
target: Element;
|
||||||
index: number;
|
index: number;
|
||||||
@ -216,7 +221,9 @@ export class Link extends Model {
|
|||||||
targetAnchor,
|
targetAnchor,
|
||||||
label: option.label,
|
label: option.label,
|
||||||
style: Util.objectClone<Style>(option.style),
|
style: Util.objectClone<Style>(option.style),
|
||||||
labelCfg: Util.objectClone<LinkLabelOption>(option.labelOptions)
|
labelCfg: Util.objectClone<LinkLabelOption>(option.labelOptions),
|
||||||
|
modelType: this.modelType,
|
||||||
|
modelName: this.modelName
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -224,7 +231,7 @@ export class Link extends Model {
|
|||||||
|
|
||||||
|
|
||||||
export class Pointer extends Model {
|
export class Pointer extends Model {
|
||||||
type = 'pointer';
|
modelType = 'pointer';
|
||||||
target: Element;
|
target: Element;
|
||||||
label: string | string[];
|
label: string | string[];
|
||||||
|
|
||||||
@ -250,7 +257,8 @@ export class Pointer extends Model {
|
|||||||
style: Util.objectClone<Style>(option.style),
|
style: Util.objectClone<Style>(option.style),
|
||||||
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
||||||
externalPointerId: null,
|
externalPointerId: null,
|
||||||
modelType: this.type
|
modelType: this.modelType,
|
||||||
|
modelName: this.modelName
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -56,7 +56,9 @@ export default G6.registerNode('link-list-node', {
|
|||||||
getAnchorPoints() {
|
getAnchorPoints() {
|
||||||
return [
|
return [
|
||||||
[0, 0.5],
|
[0, 0.5],
|
||||||
[5 / 6, 0.5]
|
[5 / 6, 0.5],
|
||||||
|
[5 / 6, 0],
|
||||||
|
[5 / 6, 1]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
63
src/RegisteredShape/twoCellNode.ts
Normal file
63
src/RegisteredShape/twoCellNode.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import * as G6 from "./../Lib/g6.js";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default G6.registerNode('two-cell-node', {
|
||||||
|
draw(cfg, group) {
|
||||||
|
cfg.size = cfg.size || [30, 10];
|
||||||
|
|
||||||
|
const width = cfg.size[0],
|
||||||
|
height = cfg.size[1];
|
||||||
|
|
||||||
|
const wrapperRect = group.addShape('rect', {
|
||||||
|
attrs: {
|
||||||
|
x: width / 2,
|
||||||
|
y: height / 2,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
stroke: cfg.style.stroke,
|
||||||
|
fill: 'transparent'
|
||||||
|
},
|
||||||
|
name: 'wrapper'
|
||||||
|
});
|
||||||
|
|
||||||
|
group.addShape('rect', {
|
||||||
|
attrs: {
|
||||||
|
x: width / 2,
|
||||||
|
y: height / 2,
|
||||||
|
width: width / 2,
|
||||||
|
height: height,
|
||||||
|
fill: cfg.style.fill,
|
||||||
|
stroke: cfg.style.stroke
|
||||||
|
},
|
||||||
|
name: 'left-rect',
|
||||||
|
draggable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cfg.label) {
|
||||||
|
const style = (cfg.labelCfg && cfg.labelCfg.style) || {};
|
||||||
|
group.addShape('text', {
|
||||||
|
attrs: {
|
||||||
|
x: width * (3 / 4),
|
||||||
|
y: height,
|
||||||
|
textAlign: 'center',
|
||||||
|
textBaseline: 'middle',
|
||||||
|
text: cfg.label,
|
||||||
|
fill: style.fill || '#000',
|
||||||
|
fontSize: style.fontSize || 16
|
||||||
|
},
|
||||||
|
name: 'text',
|
||||||
|
draggable: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrapperRect;
|
||||||
|
},
|
||||||
|
|
||||||
|
getAnchorPoints() {
|
||||||
|
return [
|
||||||
|
[0, 0.5],
|
||||||
|
[3 / 4, 0.5]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -5,6 +5,7 @@ import externalPointer from "./RegisteredShape/externalPointer";
|
|||||||
import * as G6 from "./Lib/g6.js";
|
import * as G6 from "./Lib/g6.js";
|
||||||
import linkListNode from "./RegisteredShape/linkListNode";
|
import linkListNode from "./RegisteredShape/linkListNode";
|
||||||
import binaryTreeNode from "./RegisteredShape/binaryTreeNode";
|
import binaryTreeNode from "./RegisteredShape/binaryTreeNode";
|
||||||
|
import twoCellNode from "./RegisteredShape/twoCellNode";
|
||||||
|
|
||||||
|
|
||||||
export const SV = {
|
export const SV = {
|
||||||
@ -13,7 +14,7 @@ export const SV = {
|
|||||||
Bound: Bound,
|
Bound: Bound,
|
||||||
G6,
|
G6,
|
||||||
registeredShape: [
|
registeredShape: [
|
||||||
externalPointer, linkListNode, binaryTreeNode
|
externalPointer, linkListNode, binaryTreeNode, twoCellNode
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -9,14 +9,15 @@ export class Behavior {
|
|||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
this.graphInstance = graphInstance;
|
this.graphInstance = graphInstance;
|
||||||
|
|
||||||
const interactionOptions = this.engine.interactionOptions;
|
const interactionOptions = this.engine.interactionOptions,
|
||||||
|
selectNode: boolean | string[] = interactionOptions.selectNode;
|
||||||
|
|
||||||
if(interactionOptions.dragNode) {
|
if(interactionOptions.dragNode) {
|
||||||
this.initDragNode();
|
this.initDragNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(interactionOptions.selectNode) {
|
if(interactionOptions.selectNode) {
|
||||||
this.initSelectNode();
|
this.initSelectNode(selectNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,16 +68,27 @@ export class Behavior {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化节/边选中
|
* 初始化节/边选中
|
||||||
|
* @param selectNode
|
||||||
*/
|
*/
|
||||||
private initSelectNode() {
|
private initSelectNode(selectNode: boolean | string[]) {
|
||||||
let defaultHighlightColor = '#f08a5d',
|
let defaultHighlightColor = '#f08a5d',
|
||||||
curSelectItem = null,
|
curSelectItem = null,
|
||||||
curSelectItemStyle = null;
|
curSelectItemStyle = null;
|
||||||
|
|
||||||
|
if(selectNode === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const selectCallback = ev => {
|
const selectCallback = ev => {
|
||||||
const item = ev.item,
|
const item = ev.item,
|
||||||
|
model = item.getModel(),
|
||||||
type = item.getType(),
|
type = item.getType(),
|
||||||
highlightColor = item.getModel().style.selectedColor;
|
name = model.modelName,
|
||||||
|
highlightColor = model.style.selectedColor;
|
||||||
|
|
||||||
|
if(Array.isArray(selectNode) && selectNode.find(item => item === name) === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(curSelectItem && curSelectItem !== item) {
|
if(curSelectItem && curSelectItem !== item) {
|
||||||
curSelectItem.update({
|
curSelectItem.update({
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { Util } from "../Common/util";
|
|
||||||
import { Engine } from "../engine";
|
import { Engine } from "../engine";
|
||||||
import { ConstructedData } from "../Model/modelConstructor";
|
import { ConstructedData } from "../Model/modelConstructor";
|
||||||
import { Element, Model, Pointer } from "../Model/modelData";
|
import { Element, Model, Pointer } from "../Model/modelData";
|
||||||
@ -71,7 +70,7 @@ export class Layouter {
|
|||||||
modelList.forEach(item => {
|
modelList.forEach(item => {
|
||||||
item.G6Item = item.shadowG6Item;
|
item.G6Item = item.shadowG6Item;
|
||||||
|
|
||||||
if(item.type === 'element' || item.type === 'pointer') {
|
if(item.modelType === 'element' || item.modelType === 'pointer') {
|
||||||
item.set('rotation', item.get('rotation'));
|
item.set('rotation', item.get('rotation'));
|
||||||
item.set({ x: 0, y: 0 });
|
item.set({ x: 0, y: 0 });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,28 +37,7 @@ export class Renderer {
|
|||||||
|
|
||||||
const enable: boolean = this.engine.animationOptions.enable === undefined? true: this.engine.animationOptions.enable,
|
const enable: boolean = this.engine.animationOptions.enable === undefined? true: this.engine.animationOptions.enable,
|
||||||
duration: number = this.engine.animationOptions.duration,
|
duration: number = this.engine.animationOptions.duration,
|
||||||
timingFunction: string = this.engine.animationOptions.timingFunction,
|
timingFunction: string = this.engine.animationOptions.timingFunction;
|
||||||
interactionOptions = this.engine.interactionOptions;
|
|
||||||
|
|
||||||
const modeMap = {
|
|
||||||
drag: 'drag-canvas',
|
|
||||||
zoom: 'zoom-canvas',
|
|
||||||
dragNode: {
|
|
||||||
type: 'drag-node',
|
|
||||||
shouldBegin: n => {
|
|
||||||
// 不允许拖拽外部指针
|
|
||||||
if (n.item && n.item.getModel().modelType === 'pointer') return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
defaultModes = [];
|
|
||||||
|
|
||||||
Object.keys(interactionOptions).forEach(item => {
|
|
||||||
if(interactionOptions[item] === true && modeMap[item] !== undefined) {
|
|
||||||
defaultModes.push(modeMap[item]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.graphInstance = new SV.G6.Graph({
|
this.graphInstance = new SV.G6.Graph({
|
||||||
container: DOMContainer,
|
container: DOMContainer,
|
||||||
@ -71,7 +50,7 @@ export class Renderer {
|
|||||||
},
|
},
|
||||||
fitView: this.engine.layoutOptions.fitView,
|
fitView: this.engine.layoutOptions.fitView,
|
||||||
modes: {
|
modes: {
|
||||||
default: defaultModes
|
default: this.initBehaviors()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -82,6 +61,54 @@ export class Renderer {
|
|||||||
this.animations = new Animations(duration, timingFunction);
|
this.animations = new Animations(duration, timingFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化交互行为
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
private initBehaviors() {
|
||||||
|
const interactionOptions = this.engine.interactionOptions,
|
||||||
|
dragNode: boolean | string[] = interactionOptions.dragNode,
|
||||||
|
dragNodeFilter = node => {
|
||||||
|
let model = node.item.getModel();
|
||||||
|
|
||||||
|
if(node.item === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(model.modelType === 'pointer') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof dragNode === 'boolean') {
|
||||||
|
return dragNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Array.isArray(dragNode) && dragNode.indexOf(model.modelName) > -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modeMap = {
|
||||||
|
drag: 'drag-canvas',
|
||||||
|
zoom: 'zoom-canvas',
|
||||||
|
dragNode: {
|
||||||
|
type: 'drag-node',
|
||||||
|
shouldBegin: node => dragNodeFilter(node)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
defaultModes = [];
|
||||||
|
|
||||||
|
Object.keys(interactionOptions).forEach(item => {
|
||||||
|
if(interactionOptions[item] && modeMap[item] !== undefined) {
|
||||||
|
defaultModes.push(modeMap[item]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return defaultModes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对比上一次和该次 G6Data 找出新添加的节点和边
|
* 对比上一次和该次 G6Data 找出新添加的节点和边
|
||||||
* @param prevData
|
* @param prevData
|
||||||
|
|||||||
@ -102,7 +102,7 @@ export class Engine {
|
|||||||
|
|
||||||
this.layouter.layout(this.constructedData, modelList, this.layout);
|
this.layouter.layout(this.constructedData, modelList, this.layout);
|
||||||
modelList.forEach(item => {
|
modelList.forEach(item => {
|
||||||
if(item.type === 'link') return;
|
if(item.modelType === 'link') return;
|
||||||
|
|
||||||
let model = item.G6Item.getModel(),
|
let model = item.G6Item.getModel(),
|
||||||
x = item.get('x'),
|
x = item.get('x'),
|
||||||
|
|||||||
@ -74,8 +74,8 @@ export interface AnimationOptions {
|
|||||||
export interface InteractionOptions {
|
export interface InteractionOptions {
|
||||||
drag: boolean;
|
drag: boolean;
|
||||||
zoom: boolean;
|
zoom: boolean;
|
||||||
dragNode: boolean;
|
dragNode: boolean | string[];
|
||||||
selectNode: boolean;
|
selectNode: boolean | string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,11 +5,9 @@ module.exports = {
|
|||||||
entry: './src/StructV.ts',
|
entry: './src/StructV.ts',
|
||||||
output: {
|
output: {
|
||||||
filename: './sv.js',
|
filename: './sv.js',
|
||||||
//path: path.resolve(__dirname, './../Visualizer/src/StructV'),
|
|
||||||
libraryTarget: 'umd'
|
libraryTarget: 'umd'
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
// 先尝试以ts为后缀的TypeScript源码文件
|
|
||||||
extensions: ['.ts', '.js']
|
extensions: ['.ts', '.js']
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user