Merge branch 'main' of https://gitlab.com/phenomLi/StructV2 into main
This commit is contained in:
commit
6d27c73136
@ -4,10 +4,11 @@
|
|||||||
```javascript
|
```javascript
|
||||||
1. git clone
|
1. git clone
|
||||||
2. npm install
|
2. npm install
|
||||||
|
|
||||||
|
// 开发环境:
|
||||||
3. npm run dev
|
3. npm run dev
|
||||||
|
|
||||||
|
// 打包出生产环境产物
|
||||||
|
4. npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
### 源码里一些概念解释
|
|
||||||
1. `Model`里的`defineProps`方法是干什么的?
|
|
||||||
2. `ViewManager`里面的`shadowG6Instance`属性是干什么的?
|
|
||||||
3. `ModelConstructor`里面的`constructLinks`和`constructMarkers`具体做了什么工作?
|
|
||||||
|
|||||||
12
copyDist2Anyview.js
Normal file
12
copyDist2Anyview.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const sourcePath = 'D:\\个人项目\\v\\StructV2\\dist\\sv.js';
|
||||||
|
const targetPath = 'D:\\个人项目\\anyview项目\\froend_student\\src\\pages\\student\\assets\\js\\sv.js'
|
||||||
|
|
||||||
|
|
||||||
|
function COPY(from, to) {
|
||||||
|
const file = fs.readFileSync(from);
|
||||||
|
fs.writeFileSync(to, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
COPY(sourcePath, targetPath);
|
||||||
@ -16,18 +16,17 @@ SV.registerLayout('Array', {
|
|||||||
|
|
||||||
defineOptions() {
|
defineOptions() {
|
||||||
return {
|
return {
|
||||||
element: {
|
node: {
|
||||||
default: {
|
default: {
|
||||||
type: 'indexed-node',
|
type: 'array-node',
|
||||||
label: '[id]',
|
label: '[id]',
|
||||||
size: [60, 30],
|
size: [60, 30],
|
||||||
|
labelOptions: {
|
||||||
|
style: { fontSize: 20 }
|
||||||
|
},
|
||||||
style: {
|
style: {
|
||||||
stroke: '#333',
|
stroke: '#333',
|
||||||
fill: '#95e1d3'
|
fill: '#95e1d3'
|
||||||
},
|
|
||||||
indexOptions: {
|
|
||||||
index: { position: 'bottom' },
|
|
||||||
indexTop: { position: 'top' }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -47,8 +46,9 @@ SV.registerLayout('Array', {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
behavior: {
|
indexLabel: {
|
||||||
dragNode: false
|
index: { position: 'bottom' },
|
||||||
|
indexRight: { position: 'right' }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@ -32,8 +32,9 @@ SV.registerLayout('BinaryTree', {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pointer: {
|
marker: {
|
||||||
external: {
|
external: {
|
||||||
|
type: 'pointer',
|
||||||
anchor: 0,
|
anchor: 0,
|
||||||
offset: 14,
|
offset: 14,
|
||||||
style: {
|
style: {
|
||||||
|
|||||||
86
demoV2/Layouter/PTree.js
Normal file
86
demoV2/Layouter/PTree.js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
// 解析数据:
|
||||||
|
// {
|
||||||
|
// PTree:{
|
||||||
|
// data:[
|
||||||
|
// {
|
||||||
|
// id: '1001',
|
||||||
|
// data: 'A',
|
||||||
|
// parent: -1,
|
||||||
|
// index: 0
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// id: '1002',
|
||||||
|
// data: 'B',
|
||||||
|
// parent: 0,
|
||||||
|
// index: 1
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// layouter: 'PTree'
|
||||||
|
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
SV.registerLayout('PTree', {
|
||||||
|
|
||||||
|
sourcesPreprocess(sources) {
|
||||||
|
let dataLength = sources.length;
|
||||||
|
let parentNodes = [];
|
||||||
|
let i;
|
||||||
|
|
||||||
|
for (i = 0; i < dataLength; i++) {
|
||||||
|
parentNodes.push({
|
||||||
|
id: `parent-${i}`,
|
||||||
|
data: sources[i].parent
|
||||||
|
});
|
||||||
|
}
|
||||||
|
sources[0].indexLeft = 'data';
|
||||||
|
parentNodes[0].indexLeft = 'parent';
|
||||||
|
|
||||||
|
sources.push(...parentNodes);
|
||||||
|
|
||||||
|
return sources;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
defineOptions() {
|
||||||
|
return {
|
||||||
|
node: {
|
||||||
|
default: {
|
||||||
|
type: 'rect',
|
||||||
|
label: '[data]',
|
||||||
|
size: [40, 40],
|
||||||
|
labelOptions: {
|
||||||
|
style: { fontSize: 16 }
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
stroke: '#333',
|
||||||
|
fill: '#95e1d3',
|
||||||
|
offset: 25
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
indexLabel: {
|
||||||
|
index: { position: 'top' },
|
||||||
|
indexLeft: { position: 'left' }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
layout(elements) {
|
||||||
|
let nodeLength = elements.length,
|
||||||
|
halfLength = nodeLength / 2,
|
||||||
|
size = elements[0].get('size')[0],
|
||||||
|
i;
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < nodeLength; i++) {
|
||||||
|
let x = (i % halfLength) * size;
|
||||||
|
y = Math.floor(i / halfLength) * size;
|
||||||
|
|
||||||
|
elements[i].set({ x, y });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
120
demoV2/Layouter/SqQueue.js
Normal file
120
demoV2/Layouter/SqQueue.js
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SV.registerLayout('SqQueue', {
|
||||||
|
defineOptions() {
|
||||||
|
return {
|
||||||
|
node: {
|
||||||
|
head: {
|
||||||
|
type: 'rect',
|
||||||
|
anchorPoints: [
|
||||||
|
[0.5, 0],
|
||||||
|
[1, 0.5],
|
||||||
|
[0.5, 1],
|
||||||
|
[0, 0.5]
|
||||||
|
],
|
||||||
|
size: [60, 30],
|
||||||
|
label: '[data]',
|
||||||
|
style: {
|
||||||
|
fill: '#95e1d3',
|
||||||
|
stroke: "#333",
|
||||||
|
cursor: 'pointer'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
type: 'indexed-node',
|
||||||
|
size: [60, 30],
|
||||||
|
label: '[data]',
|
||||||
|
style: {
|
||||||
|
fill: '#95e1d3',
|
||||||
|
stroke: "#333",
|
||||||
|
cursor: 'pointer'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
front: {
|
||||||
|
type: 'polyline',
|
||||||
|
sourceAnchor: 1,
|
||||||
|
targetAnchor: 5,
|
||||||
|
style: {
|
||||||
|
stroke: '#333',
|
||||||
|
endArrow: 'default'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rear: {
|
||||||
|
type: 'polyline',
|
||||||
|
sourceAnchor: 1,
|
||||||
|
targetAnchor: 5,
|
||||||
|
style: {
|
||||||
|
stroke: '#333',
|
||||||
|
endArrow: 'default'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
marker: {
|
||||||
|
external: {
|
||||||
|
type: 'pointer',
|
||||||
|
anchor: 0,
|
||||||
|
offset: 8,
|
||||||
|
labelOffset: 2,
|
||||||
|
style: {
|
||||||
|
fill: '#f08a5d'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cursor: {
|
||||||
|
type: 'cursor',
|
||||||
|
anchor: 0,
|
||||||
|
offset: 8,
|
||||||
|
labelOffset: 2,
|
||||||
|
style: {
|
||||||
|
fill: '#f08a5d'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
layout(elements) {
|
||||||
|
let head = elements.filter(item => item.type === 'head'),
|
||||||
|
head1 = head[0],
|
||||||
|
head2 = head[1],
|
||||||
|
nodes = elements.filter(item => item.type !== 'head'),
|
||||||
|
headHeight = head1.get('size')[1],
|
||||||
|
headWidth = head1.get('size')[0],
|
||||||
|
nodeHeight = 0,
|
||||||
|
x = 0, y = 0;
|
||||||
|
|
||||||
|
if (nodes.length) {
|
||||||
|
let firstNode = nodes[0];
|
||||||
|
nodeHeight = firstNode.get('size')[1];
|
||||||
|
x = -50;
|
||||||
|
y = firstNode.get('y');
|
||||||
|
|
||||||
|
for (let i = 1; i < nodes.length; i++) {
|
||||||
|
let width = nodes[i].get('size')[0];
|
||||||
|
nodes[i].set('x', nodes[i - 1].get('x') + width);
|
||||||
|
|
||||||
|
if (nodes[i].empty) {
|
||||||
|
nodes[i].set('style', {
|
||||||
|
fill: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
head1.set({ x, y: y + nodeHeight * 3 });
|
||||||
|
|
||||||
|
if (nodes.length) {
|
||||||
|
head2.set({ x, y: head1.get('y') + headHeight });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
head2.set({ x: x + headWidth, y });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -33,8 +33,8 @@
|
|||||||
#leak {
|
#leak {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 100px;
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
top: 100px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
@ -60,6 +60,8 @@
|
|||||||
<button id="btn-prev">prev</button>
|
<button id="btn-prev">prev</button>
|
||||||
<button id="btn-next">next</button>
|
<button id="btn-next">next</button>
|
||||||
<button id="resize">resize</button>
|
<button id="resize">resize</button>
|
||||||
|
<button id="relayout">relayout</button>
|
||||||
|
<button id="switch-mode">switch mode</button>
|
||||||
<span id="pos"></span>
|
<span id="pos"></span>
|
||||||
|
|
||||||
<script src="./../dist/sv.js"></script>
|
<script src="./../dist/sv.js"></script>
|
||||||
@ -82,64 +84,42 @@
|
|||||||
<script src="./Layouter/LinkStack.js"></script>
|
<script src="./Layouter/LinkStack.js"></script>
|
||||||
<script src="./Layouter/AdjoinMatrixGraph.js"></script>
|
<script src="./Layouter/AdjoinMatrixGraph.js"></script>
|
||||||
<script src="./Layouter/AdjoinTableGraph.js"></script>
|
<script src="./Layouter/AdjoinTableGraph.js"></script>
|
||||||
|
<script src="./Layouter/SqQueue.js"></script>
|
||||||
|
<script src="./Layouter/PTree.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
const curSelectData = { element: null, style: null };
|
const curSelectData = { element: null, style: null };
|
||||||
|
|
||||||
let cur = SV(document.getElementById('container'), {
|
let cur = SV(document.getElementById('container'), {
|
||||||
view: {
|
view: {
|
||||||
leakAreaHeight: 0.25,
|
leakAreaHeight: 130,
|
||||||
groupPadding: 40,
|
groupPadding: 40,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let data = [{
|
let data = [{
|
||||||
"LinkList0": {
|
Array: {
|
||||||
"data": [
|
data: [{ id: 1, data: 1, external: 'list' }, { id: 2, data: 2 }, { id: 3, data: 3 }],
|
||||||
{ id: 0, data: 'A', next: 1 },
|
layouter: 'Array'
|
||||||
{ id: 1, data: 'B' }
|
|
||||||
],
|
|
||||||
"layouter": "LinkList"
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"LinkList0": {
|
Array: {
|
||||||
"data": [
|
data: [{ id: 1, data: 1 }, { id: 2, data: 2 }],
|
||||||
{ id: 0, data: 'A', next: 1 },
|
layouter: 'Array'
|
||||||
{ id: 1, data: 'B', next: 2 },
|
|
||||||
{ id: 2, data: 'C' }
|
|
||||||
],
|
|
||||||
"layouter": "LinkList"
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"LinkList0": {
|
Array: {
|
||||||
"data": [
|
data: [{ id: 1, data: 1 }, { id: 5, data: 5 }],
|
||||||
{ id: 0, data: 'A', next: 1 },
|
layouter: 'Array'
|
||||||
{ id: 1, data: 'B', next: 2 },
|
|
||||||
{ id: 2, data: 'C', next: 3 },
|
|
||||||
{ id: 3, data: 'D' }
|
|
||||||
],
|
|
||||||
"layouter": "LinkList"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"LinkList0": {
|
|
||||||
"data": [
|
|
||||||
{ id: 0, data: 'A', next: 1 },
|
|
||||||
{ id: 1, data: 'B', next: 2, freed: true }
|
|
||||||
],
|
|
||||||
"layouter": "LinkList"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"LinkList0": {
|
|
||||||
"data": [
|
|
||||||
{ id: 0, data: 'A' }
|
|
||||||
],
|
|
||||||
"layouter": "LinkList"
|
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let dataIndex = 0,
|
let dataIndex = 0,
|
||||||
curData = data[dataIndex];
|
curData = data[dataIndex];
|
||||||
|
|
||||||
@ -164,10 +144,18 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('resize').addEventListener('click', e => {
|
document.getElementById('resize').addEventListener('click', e => {
|
||||||
container.style.height = 400 + 'px';
|
container.style.height = 800 + 'px';
|
||||||
cur.resize(container.offsetWidth, container.offsetHeight);
|
cur.resize(container.offsetWidth, container.offsetHeight);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById('relayout').addEventListener('click', e => {
|
||||||
|
cur.reLayout();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('switch-mode').addEventListener('click', e => {
|
||||||
|
cur.updateStyle('Array', newArrayOption);
|
||||||
|
});
|
||||||
|
|
||||||
const leak = document.getElementById('leak');
|
const leak = document.getElementById('leak');
|
||||||
|
|
||||||
cur.on('onLeakAreaUpdate', payload => {
|
cur.on('onLeakAreaUpdate', payload => {
|
||||||
|
|||||||
14117
dist/sv.js
vendored
14117
dist/sv.js
vendored
File diff suppressed because one or more lines are too long
14
package.json
14
package.json
@ -1,15 +1,19 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antv/g6": "^4.4.1",
|
"@antv/g6": "^4.4.1",
|
||||||
"awesome-typescript-loader": "^5.2.1",
|
"merge": "^2.1.1"
|
||||||
"typescript": "^3.2.2",
|
|
||||||
"webpack": "^4.28.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"merge": "^2.1.1",
|
||||||
|
"ts-loader": "^5.2.1",
|
||||||
|
"typescript": "^3.2.2",
|
||||||
|
"webpack": "^4.46.0",
|
||||||
"webpack-cli": "^3.2.3"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc && webpack",
|
"build": "webpack --config webpack.config.product.js",
|
||||||
"dev": "webpack --w"
|
"dep": "webpack --config webpack.config.product.js && node copyDist2Anyview.js",
|
||||||
|
"dev": "webpack --w --config webpack.config.develop.js",
|
||||||
|
"copy": "node copyDist2Anyview.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,32 +5,25 @@ import { ViewContainer } from "../View/viewContainer";
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化视图拖拽功能
|
*
|
||||||
* @param g6Instance
|
* @param g6Instance
|
||||||
* @param hasLeak
|
* @param hasLeak
|
||||||
*/
|
*/
|
||||||
export function InitDragCanvasWithLeak(viewContainer: ViewContainer) {
|
export function InitDragCanvasWithLeak(viewContainer: ViewContainer) {
|
||||||
let g6Instance = viewContainer.getG6Instance(),
|
let g6Instance = viewContainer.getG6Instance(),
|
||||||
isDragStart = false,
|
prevDy = 0;
|
||||||
startPositionY = 0,
|
|
||||||
currentLeakAreaY = 0;
|
|
||||||
|
|
||||||
g6Instance.on('canvas:dragstart', event => {
|
g6Instance.on('viewportchange', event => {
|
||||||
isDragStart = true;
|
if(event.action !== 'translate') {
|
||||||
startPositionY = event.canvasY;
|
|
||||||
currentLeakAreaY = viewContainer.leakAreaY;
|
|
||||||
});
|
|
||||||
|
|
||||||
g6Instance.on('canvas:drag', event => {
|
|
||||||
if(!isDragStart) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let zoom = g6Instance.getZoom(),
|
let translateX = event.matrix[7],
|
||||||
dy = (event.canvasY - startPositionY) / zoom,
|
dy = translateX- prevDy;
|
||||||
leakAreaY = currentLeakAreaY + dy;
|
|
||||||
|
|
||||||
viewContainer.leakAreaY = leakAreaY;
|
prevDy = translateX;
|
||||||
|
|
||||||
|
viewContainer.leakAreaY = viewContainer.leakAreaY + dy;
|
||||||
if (viewContainer.hasLeak) {
|
if (viewContainer.hasLeak) {
|
||||||
EventBus.emit('onLeakAreaUpdate', {
|
EventBus.emit('onLeakAreaUpdate', {
|
||||||
leakAreaY: viewContainer.leakAreaY,
|
leakAreaY: viewContainer.leakAreaY,
|
||||||
@ -38,11 +31,6 @@ export function InitDragCanvasWithLeak(viewContainer: ViewContainer) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
g6Instance.on('canvas:dragend', event => {
|
|
||||||
isDragStart = false;
|
|
||||||
startPositionY = 0;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,66 +1,38 @@
|
|||||||
import { Graph } from "@antv/g6-pc";
|
import { Graph } from "@antv/g6";
|
||||||
import { SVNode } from "../Model/SVNode";
|
import { SVNode } from "../Model/SVNode";
|
||||||
import { LayoutGroupOptions } from "../options";
|
import { SVNodeAppendage } from "../Model/SVNodeAppendage";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在初始化渲染器之后,修正节点拖拽时,外部指针没有跟着动的问题
|
* 在初始化渲染器之后,修正节点拖拽时,外部指针或者其他 appendage 没有跟着动的问题
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export function FixNodeMarkerDrag(g6Instance: Graph, optionsTable: { [key: string]: LayoutGroupOptions }) {
|
export function FixNodeMarkerDrag(g6Instance: Graph) {
|
||||||
let dragActive: boolean = false;
|
let dragActive: boolean = false,
|
||||||
|
nodeData: { node: SVNode, startX: number, startY: number },
|
||||||
const nodeData = {
|
appendagesData: { appendage: SVNodeAppendage, startX: number, startY: number }[] = [];
|
||||||
node: null,
|
|
||||||
startX: 0,
|
|
||||||
startY: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
const markerData = {
|
|
||||||
marker: null,
|
|
||||||
startX: 0,
|
|
||||||
startY: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
const freedLabelData = {
|
|
||||||
freedLabel: null,
|
|
||||||
startX: 0,
|
|
||||||
startY: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
g6Instance.on('node:dragstart', event => {
|
g6Instance.on('node:dragstart', event => {
|
||||||
nodeData.node = event.item['SVModel'];
|
let node: SVNode = event.item['SVModel'];
|
||||||
let node: SVNode = nodeData.node;
|
|
||||||
|
|
||||||
if (node.isNode() === false || node.leaked) {
|
if (node.isNode() === false || node.leaked) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dragNode = optionsTable[node.layout].behavior.dragNode;
|
|
||||||
|
|
||||||
if (dragNode === false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(dragNode) && dragNode.find(item => item === node.sourceType) === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dragActive = true;
|
dragActive = true;
|
||||||
nodeData.startX = event.canvasX;
|
nodeData = {
|
||||||
nodeData.startY = event.canvasY;
|
node,
|
||||||
|
startX: event.canvasX,
|
||||||
|
startY: event.canvasY
|
||||||
|
};
|
||||||
|
|
||||||
if (node.marker) {
|
node.appendages.forEach(item => {
|
||||||
markerData.marker = node.marker;
|
appendagesData.push({
|
||||||
markerData.startX = markerData.marker.get('x');
|
appendage: item,
|
||||||
markerData.startY = markerData.marker.get('y');
|
startX: item.get('x'),
|
||||||
}
|
startY: item.get('y')
|
||||||
|
});
|
||||||
if(node.freedLabel) {
|
});
|
||||||
freedLabelData.freedLabel = node.freedLabel;
|
|
||||||
freedLabelData.startX = freedLabelData.freedLabel.get('x');
|
|
||||||
freedLabelData.startY = freedLabelData.freedLabel.get('y');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
g6Instance.on('node:dragend', event => {
|
g6Instance.on('node:dragend', event => {
|
||||||
@ -68,25 +40,15 @@ export function FixNodeMarkerDrag(g6Instance: Graph, optionsTable: { [key: strin
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let distanceX = event.canvasX - nodeData.startX,
|
let node: SVNode = nodeData.node;
|
||||||
distanceY = event.canvasY - nodeData.startY,
|
|
||||||
nodeX = nodeData.node.get('x'),
|
|
||||||
nodeY = nodeData.node.get('y');
|
|
||||||
|
|
||||||
nodeData.node.set({
|
node.set({
|
||||||
x: nodeX + distanceX,
|
x: node.G6Item.getModel().x,
|
||||||
y: nodeY + distanceY
|
y: node.G6Item.getModel().y
|
||||||
});
|
});
|
||||||
|
|
||||||
nodeData.node = null;
|
nodeData = null;
|
||||||
nodeData.startX = 0;
|
appendagesData.length = 0;
|
||||||
nodeData.startY = 0;
|
|
||||||
markerData.marker = null;
|
|
||||||
markerData.startX = 0;
|
|
||||||
markerData.startY = 0;
|
|
||||||
freedLabelData.freedLabel = null;
|
|
||||||
freedLabelData.startX = 0;
|
|
||||||
freedLabelData.startY = 0;
|
|
||||||
dragActive = false;
|
dragActive = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -99,18 +61,11 @@ export function FixNodeMarkerDrag(g6Instance: Graph, optionsTable: { [key: strin
|
|||||||
dy = ev.canvasY - nodeData.startY,
|
dy = ev.canvasY - nodeData.startY,
|
||||||
zoom = g6Instance.getZoom();
|
zoom = g6Instance.getZoom();
|
||||||
|
|
||||||
if(markerData.marker) {
|
appendagesData.forEach(item => {
|
||||||
markerData.marker.set({
|
item.appendage.set({
|
||||||
x: markerData.startX + dx / zoom,
|
x: item.startX + dx / zoom,
|
||||||
y: markerData.startY + dy / zoom
|
y: item.startY + dy / zoom
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
if(freedLabelData.freedLabel) {
|
|
||||||
freedLabelData.freedLabel.set({
|
|
||||||
x: freedLabelData.startX + dx / zoom,
|
|
||||||
y: freedLabelData.startY + dy / zoom
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1,5 +1,4 @@
|
|||||||
import { SVModel } from "../Model/SVModel";
|
import { SVModel } from "../Model/SVModel";
|
||||||
import { LayoutGroupOptions } from "../options";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -8,15 +7,8 @@ import { LayoutGroupOptions } from "../options";
|
|||||||
* @param optionsTable
|
* @param optionsTable
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function InitViewBehaviors(optionsTable: { [key: string]: LayoutGroupOptions }) {
|
export function InitViewBehaviors() {
|
||||||
const dragNodeTable: { [key: string]: boolean | string[] } = {},
|
const defaultModes = [];
|
||||||
selectNodeTable: { [key: string]: boolean | string[] } = {},
|
|
||||||
defaultModes = [];
|
|
||||||
|
|
||||||
Object.keys(optionsTable).forEach(item => {
|
|
||||||
dragNodeTable[item] = optionsTable[item].behavior.dragNode;
|
|
||||||
selectNodeTable[item] = optionsTable[item].behavior.selectNode;
|
|
||||||
});
|
|
||||||
|
|
||||||
const dragNodeFilter = event => {
|
const dragNodeFilter = event => {
|
||||||
let g6Item = event.item,
|
let g6Item = event.item,
|
||||||
@ -26,19 +18,9 @@ export function InitViewBehaviors(optionsTable: { [key: string]: LayoutGroupOpti
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dragNode = optionsTable[node.layout].behavior.dragNode;
|
|
||||||
|
|
||||||
if (typeof dragNode === 'boolean') {
|
|
||||||
return dragNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(dragNode) && dragNode.indexOf(node.sourceType) > -1) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectNodeFilter = event => {
|
const selectNodeFilter = event => {
|
||||||
let g6Item = event.item,
|
let g6Item = event.item,
|
||||||
node: SVModel = g6Item.SVModel;
|
node: SVModel = g6Item.SVModel;
|
||||||
@ -47,19 +29,9 @@ export function InitViewBehaviors(optionsTable: { [key: string]: LayoutGroupOpti
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectNode = optionsTable[node.layout].behavior.selectNode;
|
|
||||||
|
|
||||||
if (typeof selectNode === 'boolean') {
|
|
||||||
return selectNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(selectNode) && selectNode.indexOf(node.sourceType) > -1) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultModes.push({
|
defaultModes.push({
|
||||||
type: 'drag-node',
|
type: 'drag-node',
|
||||||
shouldBegin: dragNodeFilter
|
shouldBegin: dragNodeFilter
|
||||||
@ -69,6 +41,10 @@ export function InitViewBehaviors(optionsTable: { [key: string]: LayoutGroupOpti
|
|||||||
type: 'drag-canvas'
|
type: 'drag-canvas'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// defaultModes.push({
|
||||||
|
// type: 'zoom-canvas'
|
||||||
|
// });
|
||||||
|
|
||||||
defaultModes.push({
|
defaultModes.push({
|
||||||
type: 'click-select',
|
type: 'click-select',
|
||||||
shouldBegin: selectNodeFilter
|
shouldBegin: selectNodeFilter
|
||||||
|
|||||||
@ -1,59 +0,0 @@
|
|||||||
import { Graph, IGroup } from "@antv/g6-pc";
|
|
||||||
import { ext } from '@antv/matrix-util';
|
|
||||||
|
|
||||||
const transform = ext.transform;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化视图缩放功能
|
|
||||||
* @param g6Instance
|
|
||||||
* @param generalModelsGroup
|
|
||||||
*/
|
|
||||||
export function InitZoomCanvas(g6Instance: Graph, g6GeneralGroup: IGroup) {
|
|
||||||
const minZoom = 0.2,
|
|
||||||
maxZoom = 2,
|
|
||||||
step = 0.15;
|
|
||||||
|
|
||||||
g6Instance.on('wheel', event => {
|
|
||||||
let delta = event.wheelDelta,
|
|
||||||
matrix = g6GeneralGroup.getMatrix(),
|
|
||||||
center = [event.x, event.y],
|
|
||||||
targetScale = 1;
|
|
||||||
|
|
||||||
if (delta > 0) {
|
|
||||||
targetScale += step;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delta < 0) {
|
|
||||||
targetScale -= step;
|
|
||||||
}
|
|
||||||
|
|
||||||
matrix = transform(matrix, [
|
|
||||||
['t', -center[0], -center[1]],
|
|
||||||
['s', targetScale, targetScale],
|
|
||||||
['t', center[0], center[1]],
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ((minZoom && matrix[0] < minZoom) || (maxZoom && matrix[0] > maxZoom)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
g6GeneralGroup.setMatrix(matrix);
|
|
||||||
g6Instance.paint();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
67
src/BehaviorHelper/zoomCanvasWithLeak.ts
Normal file
67
src/BehaviorHelper/zoomCanvasWithLeak.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { EventBus } from "../Common/eventBus";
|
||||||
|
import { ViewContainer } from "../View/viewContainer";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缩放这里搞不出来,尽力了
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param g6Instance
|
||||||
|
* @param generalModelsGroup
|
||||||
|
*/
|
||||||
|
export function InitZoomCanvasWithLeak(viewContainer: ViewContainer) {
|
||||||
|
let g6Instance = viewContainer.getG6Instance(),
|
||||||
|
prevDy = 0;
|
||||||
|
|
||||||
|
let prevZoom = 1;
|
||||||
|
|
||||||
|
// g6Instance.on('viewportchange', event => {
|
||||||
|
// if(event.action !== 'zoom') {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// console.log(event.matrix);
|
||||||
|
|
||||||
|
// viewContainer.leakAreaY = event.matrix[4] * viewContainer.leakAreaY + event.matrix[7];
|
||||||
|
// if (viewContainer.hasLeak) {
|
||||||
|
// EventBus.emit('onLeakAreaUpdate', {
|
||||||
|
// leakAreaY: viewContainer.leakAreaY,
|
||||||
|
// hasLeak: viewContainer.hasLeak
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
g6Instance.on('wheelzoom', event => {
|
||||||
|
let dy = event.y - viewContainer.leakAreaY,
|
||||||
|
dZoom = prevZoom - g6Instance.getZoom();
|
||||||
|
|
||||||
|
prevZoom = g6Instance.getZoom();
|
||||||
|
|
||||||
|
viewContainer.leakAreaY = viewContainer.leakAreaY + dy * dZoom;
|
||||||
|
if (viewContainer.hasLeak) {
|
||||||
|
EventBus.emit('onLeakAreaUpdate', {
|
||||||
|
leakAreaY: viewContainer.leakAreaY,
|
||||||
|
hasLeak: viewContainer.hasLeak
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -2,6 +2,7 @@ import { Util } from "./util";
|
|||||||
import { BoundingRect, Bound } from "./boundingRect";
|
import { BoundingRect, Bound } from "./boundingRect";
|
||||||
import { SVModel } from "../Model/SVModel";
|
import { SVModel } from "../Model/SVModel";
|
||||||
import { ext } from '@antv/matrix-util';
|
import { ext } from '@antv/matrix-util';
|
||||||
|
import { SVLink } from "../Model/SVLink";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { EdgeConfig, GraphData, NodeConfig } from "@antv/g6-core";
|
|||||||
import { LayoutGroup, LayoutGroupTable } from "../Model/modelConstructor";
|
import { LayoutGroup, LayoutGroupTable } from "../Model/modelConstructor";
|
||||||
import { SVLink } from "../Model/SVLink";
|
import { SVLink } from "../Model/SVLink";
|
||||||
import { SVModel } from "../Model/SVModel";
|
import { SVModel } from "../Model/SVModel";
|
||||||
import { SV } from "../StructV";
|
import { Util as G6Util } from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,7 +25,7 @@ export const Util = {
|
|||||||
* @param obj
|
* @param obj
|
||||||
*/
|
*/
|
||||||
objectClone<T extends Object>(obj: T): T {
|
objectClone<T extends Object>(obj: T): T {
|
||||||
return obj? JSON.parse(JSON.stringify(obj)): { };
|
return obj? JSON.parse(JSON.stringify(obj)): null;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,7 +132,7 @@ export const Util = {
|
|||||||
* @param rotation
|
* @param rotation
|
||||||
*/
|
*/
|
||||||
calcRotateMatrix(matrix: number[], rotation: number): number[] {
|
calcRotateMatrix(matrix: number[], rotation: number): number[] {
|
||||||
const Mat3 = SV.G6.Util.mat3;
|
const Mat3 = G6Util.mat3;
|
||||||
Mat3.rotate(matrix, matrix, rotation);
|
Mat3.rotate(matrix, matrix, rotation);
|
||||||
return matrix;
|
return matrix;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,8 +24,7 @@ export class SVLink extends SVModel {
|
|||||||
this.G6ModelProps = this.generateG6ModelProps(options);
|
this.G6ModelProps = this.generateG6ModelProps(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generateG6ModelProps(options: LinkOption): EdgeConfig {
|
||||||
protected generateG6ModelProps(options: LinkOption): EdgeConfig {
|
|
||||||
let sourceAnchor = options.sourceAnchor,
|
let sourceAnchor = options.sourceAnchor,
|
||||||
targetAnchor = options.targetAnchor;
|
targetAnchor = options.targetAnchor;
|
||||||
|
|
||||||
|
|||||||
@ -1,51 +0,0 @@
|
|||||||
import { INode, NodeConfig } from "@antv/g6-core";
|
|
||||||
import { Util } from "../Common/util";
|
|
||||||
import { MarkerOption, NodeLabelOption, Style } from "../options";
|
|
||||||
import { SVModel } from "./SVModel";
|
|
||||||
import { SVNode } from "./SVNode";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export class SVMarker extends SVModel {
|
|
||||||
public target: SVNode;
|
|
||||||
public label: string | string[];
|
|
||||||
public anchor: number;
|
|
||||||
|
|
||||||
public shadowG6Item: INode;
|
|
||||||
public G6Item: INode;
|
|
||||||
|
|
||||||
constructor(id: string, type: string, group: string, layout: string, label: string | string[], target: SVNode, options: MarkerOption) {
|
|
||||||
super(id, type, group, layout, 'marker');
|
|
||||||
|
|
||||||
this.target = target;
|
|
||||||
this.label = label;
|
|
||||||
|
|
||||||
this.target.marker = this;
|
|
||||||
this.G6ModelProps = this.generateG6ModelProps(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected generateG6ModelProps(options: MarkerOption): NodeConfig {
|
|
||||||
this.anchor = options.anchor;
|
|
||||||
|
|
||||||
const type = options.type,
|
|
||||||
defaultSize: [number, number] = type === 'pointer'? [8, 30]: [12, 12];
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
rotation: 0,
|
|
||||||
type: options.type || 'marker',
|
|
||||||
size: options.size || defaultSize,
|
|
||||||
anchorPoints: null,
|
|
||||||
label: typeof this.label === 'string'? this.label: this.label.join(', '),
|
|
||||||
style: Util.objectClone<Style>(options.style),
|
|
||||||
labelCfg: Util.objectClone<NodeLabelOption>(options.labelOptions)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public getLabelSizeRadius(): number {
|
|
||||||
const { width, height } = this.shadowG6Item.getContainer().getChildren()[2].getBBox();
|
|
||||||
return width > height? width: height;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import { Util } from "../Common/util";
|
import { Util } from "../Common/util";
|
||||||
import { ModelOption, Style } from "../options";
|
import { Style } from "../options";
|
||||||
import { BoundingRect } from "../Common/boundingRect";
|
import { BoundingRect } from "../Common/boundingRect";
|
||||||
import { EdgeConfig, Item, NodeConfig } from "@antv/g6-core";
|
import { EdgeConfig, Item, NodeConfig } from "@antv/g6-core";
|
||||||
import { Point } from "@antv/g-base";
|
import { Graph } from "_@antv_g6-pc@0.5.0@@antv/g6-pc";
|
||||||
|
import merge from 'merge';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -12,12 +12,15 @@ export class SVModel {
|
|||||||
public id: string;
|
public id: string;
|
||||||
public sourceType: string;
|
public sourceType: string;
|
||||||
|
|
||||||
|
public g6Instance: Graph;
|
||||||
|
public shadowG6Instance: Graph;
|
||||||
public group: string;
|
public group: string;
|
||||||
public layout: string;
|
public layout: string;
|
||||||
public G6ModelProps: NodeConfig | EdgeConfig;
|
public G6ModelProps: NodeConfig | EdgeConfig;
|
||||||
public shadowG6Item: Item;
|
public shadowG6Item: Item;
|
||||||
public G6Item: Item;
|
public G6Item: Item;
|
||||||
|
|
||||||
|
public preLayout: boolean; // 是否进入预备布局阶段
|
||||||
public discarded: boolean;
|
public discarded: boolean;
|
||||||
public freed: boolean;
|
public freed: boolean;
|
||||||
public leaked: boolean;
|
public leaked: boolean;
|
||||||
@ -26,6 +29,9 @@ export class SVModel {
|
|||||||
private transformMatrix: number[];
|
private transformMatrix: number[];
|
||||||
private modelType: string;
|
private modelType: string;
|
||||||
|
|
||||||
|
public layoutX: number;
|
||||||
|
public layoutY: number;
|
||||||
|
|
||||||
constructor(id: string, type: string, group: string, layout: string, modelType: string) {
|
constructor(id: string, type: string, group: string, layout: string, modelType: string) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.sourceType = type;
|
this.sourceType = type;
|
||||||
@ -33,6 +39,7 @@ export class SVModel {
|
|||||||
this.layout = layout;
|
this.layout = layout;
|
||||||
this.shadowG6Item = null;
|
this.shadowG6Item = null;
|
||||||
this.G6Item = null;
|
this.G6Item = null;
|
||||||
|
this.preLayout = false;
|
||||||
this.discarded = false;
|
this.discarded = false;
|
||||||
this.freed = false;
|
this.freed = false;
|
||||||
this.leaked = false;
|
this.leaked = false;
|
||||||
@ -45,7 +52,7 @@ export class SVModel {
|
|||||||
* 定义 G6 model 的属性
|
* 定义 G6 model 的属性
|
||||||
* @param option
|
* @param option
|
||||||
*/
|
*/
|
||||||
protected generateG6ModelProps(options: ModelOption) {
|
generateG6ModelProps(options: unknown): NodeConfig | EdgeConfig {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +87,7 @@ export class SVModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (attr === 'style' || attr === 'labelCfg') {
|
if (attr === 'style' || attr === 'labelCfg') {
|
||||||
Object.assign(this.G6ModelProps[attr], value);
|
this.G6ModelProps[attr] = merge(this.G6ModelProps[attr] || {}, value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.G6ModelProps[attr] = value;
|
this.G6ModelProps[attr] = value;
|
||||||
@ -93,24 +100,43 @@ export class SVModel {
|
|||||||
|
|
||||||
// 更新G6Item
|
// 更新G6Item
|
||||||
if (this.G6Item) {
|
if (this.G6Item) {
|
||||||
if(attr === 'x' || attr === 'y') {
|
if (this.preLayout) {
|
||||||
this.G6Item.updatePosition({ [attr]: value } as Point);
|
const G6ItemModel = this.G6Item.getModel();
|
||||||
this.G6Item.refresh();
|
G6ItemModel[attr] = value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.G6Item.update(this.G6ModelProps);
|
this.g6Instance.updateItem(this.G6Item, this.G6ModelProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新shadowG6Item
|
// 更新shadowG6Item
|
||||||
if (this.shadowG6Item) {
|
if (this.shadowG6Item) {
|
||||||
if(attr === 'x' || attr === 'y') {
|
this.shadowG6Instance.updateItem(this.shadowG6Item, this.G6ModelProps);
|
||||||
this.shadowG6Item.updatePosition({ [attr]: value } as Point);
|
|
||||||
this.shadowG6Item.refresh();
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
this.shadowG6Item.update(this.G6ModelProps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param G6ModelProps
|
||||||
|
*/
|
||||||
|
updateG6ModelStyle(G6ModelProps: NodeConfig | EdgeConfig) {
|
||||||
|
const newG6ModelProps = {
|
||||||
|
style: {
|
||||||
|
...G6ModelProps.style
|
||||||
|
},
|
||||||
|
labelCfg: {
|
||||||
|
...G6ModelProps.labelCfg
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.G6ModelProps = merge(this.G6ModelProps, newG6ModelProps);
|
||||||
|
|
||||||
|
if (this.G6Item) {
|
||||||
|
this.g6Instance.updateItem(this.G6Item, this.G6ModelProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.shadowG6Item) {
|
||||||
|
this.shadowG6Instance.updateItem(this.shadowG6Item, this.G6ModelProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,98 +1,34 @@
|
|||||||
import { INode, NodeConfig } from "@antv/g6-core";
|
import { INode, NodeConfig } from "@antv/g6-core";
|
||||||
import { Util } from "../Common/util";
|
import { Util } from "../Common/util";
|
||||||
import { NodeIndexOption, NodeLabelOption, NodeOption, Style } from "../options";
|
import { NodeLabelOption, NodeOption, Style } from "../options";
|
||||||
import { SourceNode } from "../sources";
|
import { SourceNode } from "../sources";
|
||||||
import { SVLink } from "./SVLink";
|
import { SVLink } from "./SVLink";
|
||||||
import { SVMarker } from "./SVMarker";
|
|
||||||
import { SVModel } from "./SVModel";
|
import { SVModel } from "./SVModel";
|
||||||
|
import { SVAddressLabel, SVFreedLabel, SVIndexLabel, SVMarker, SVNodeAppendage } from "./SVNodeAppendage";
|
||||||
|
|
||||||
|
|
||||||
export class SVFreedLabel extends SVModel {
|
|
||||||
public node: SVNode;
|
|
||||||
|
|
||||||
constructor(id: string, type: string, group: string, layout: string, node: SVNode) {
|
|
||||||
super(id, type, group, layout, 'freedLabel');
|
|
||||||
|
|
||||||
this.node = node;
|
|
||||||
this.node.freedLabel = this;
|
|
||||||
this.G6ModelProps = this.generateG6ModelProps();
|
|
||||||
}
|
|
||||||
|
|
||||||
generateG6ModelProps() {
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
type: 'rect',
|
|
||||||
label: '已释放',
|
|
||||||
labelCfg: {
|
|
||||||
style: {
|
|
||||||
fill: '#b83b5e',
|
|
||||||
opacity: 0.6
|
|
||||||
}
|
|
||||||
},
|
|
||||||
size: [0, 0],
|
|
||||||
style: {
|
|
||||||
stroke: null,
|
|
||||||
fill: 'transparent'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export class SVLeakAddress extends SVModel {
|
|
||||||
public node: SVNode;
|
|
||||||
private sourceId: string;
|
|
||||||
|
|
||||||
constructor(id: string, type: string, group: string, layout: string, node: SVNode) {
|
|
||||||
super(id, type, group, layout, 'leakAddress');
|
|
||||||
|
|
||||||
this.node = node;
|
|
||||||
this.sourceId = node.sourceId;
|
|
||||||
this.node.leakAddress = this;
|
|
||||||
this.G6ModelProps = this.generateG6ModelProps();
|
|
||||||
}
|
|
||||||
|
|
||||||
generateG6ModelProps() {
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
type: 'rect',
|
|
||||||
label: this.sourceId,
|
|
||||||
labelCfg: {
|
|
||||||
style: {
|
|
||||||
fill: '#666',
|
|
||||||
fontSize: 16
|
|
||||||
}
|
|
||||||
},
|
|
||||||
size: [0, 0],
|
|
||||||
style: {
|
|
||||||
stroke: null,
|
|
||||||
fill: 'transparent'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export class SVNode extends SVModel {
|
export class SVNode extends SVModel {
|
||||||
public sourceId: string;
|
public sourceId: string;
|
||||||
public sourceNode: SourceNode;
|
public sourceNode: SourceNode;
|
||||||
public marker: SVMarker;
|
|
||||||
public freedLabel: SVFreedLabel;
|
|
||||||
public leakAddress: SVLeakAddress;
|
|
||||||
public links: {
|
public links: {
|
||||||
inDegree: SVLink[];
|
inDegree: SVLink[];
|
||||||
outDegree: SVLink[];
|
outDegree: SVLink[];
|
||||||
};
|
};
|
||||||
|
|
||||||
private label: string | string[];
|
private label: string | string[];
|
||||||
|
private disable: boolean;
|
||||||
|
|
||||||
public shadowG6Item: INode;
|
public shadowG6Item: INode;
|
||||||
public G6Item: INode;
|
public G6Item: INode;
|
||||||
|
|
||||||
|
public marker: SVMarker;
|
||||||
|
public freedLabel: SVFreedLabel;
|
||||||
|
public indexLabel: SVIndexLabel;
|
||||||
|
public addressLabel: SVAddressLabel;
|
||||||
|
public appendages: SVNodeAppendage[];
|
||||||
|
|
||||||
constructor(id: string, type: string, group: string, layout: string, sourceNode: SourceNode, label: string | string[], options: NodeOption) {
|
constructor(id: string, type: string, group: string, layout: string, sourceNode: SourceNode, label: string | string[], options: NodeOption) {
|
||||||
super(id, type, group, layout, 'node');
|
super(id, type, group, layout, 'node');
|
||||||
|
|
||||||
@ -108,22 +44,15 @@ export class SVNode extends SVModel {
|
|||||||
this.sourceNode = sourceNode;
|
this.sourceNode = sourceNode;
|
||||||
this.sourceId = sourceNode.id.toString();
|
this.sourceId = sourceNode.id.toString();
|
||||||
|
|
||||||
this.marker = null;
|
|
||||||
this.links = { inDegree: [], outDegree: [] };
|
this.links = { inDegree: [], outDegree: [] };
|
||||||
|
this.appendages = [];
|
||||||
this.sourceNode = sourceNode;
|
this.sourceNode = sourceNode;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
this.G6ModelProps = this.generateG6ModelProps(options);
|
this.G6ModelProps = this.generateG6ModelProps(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected generateG6ModelProps(options: NodeOption): NodeConfig {
|
generateG6ModelProps(options: NodeOption): NodeConfig {
|
||||||
let indexOptions = Util.objectClone<NodeIndexOption>(options.indexOptions);
|
const style = Util.objectClone<Style>(options.style);
|
||||||
|
|
||||||
if (indexOptions) {
|
|
||||||
Object.keys(indexOptions).map(key => {
|
|
||||||
let indexOptionItem = indexOptions[key];
|
|
||||||
indexOptionItem.value = this.sourceNode[key] ?? '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...this.sourceNode,
|
...this.sourceNode,
|
||||||
@ -135,9 +64,11 @@ export class SVNode extends SVModel {
|
|||||||
size: options.size || [60, 30],
|
size: options.size || [60, 30],
|
||||||
anchorPoints: options.anchorPoints,
|
anchorPoints: options.anchorPoints,
|
||||||
label: this.label as string,
|
label: this.label as string,
|
||||||
style: Util.objectClone<Style>(options.style),
|
style: {
|
||||||
labelCfg: Util.objectClone<NodeLabelOption>(options.labelOptions),
|
...style,
|
||||||
indexCfg: indexOptions
|
fill: this.disable ? '#ccc' : style.fill
|
||||||
|
},
|
||||||
|
labelCfg: Util.objectClone<NodeLabelOption>(options.labelOptions)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
181
src/Model/SVNodeAppendage.ts
Normal file
181
src/Model/SVNodeAppendage.ts
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
import { INode, NodeConfig, EdgeConfig } from "@antv/g6-core";
|
||||||
|
import { Util } from "../Common/util";
|
||||||
|
import { AddressLabelOption, IndexLabelOption, MarkerOption, NodeLabelOption, Style } from "../options";
|
||||||
|
import { SVModel } from "./SVModel";
|
||||||
|
import { SVNode } from "./SVNode";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export class SVNodeAppendage extends SVModel {
|
||||||
|
public target: SVNode;
|
||||||
|
|
||||||
|
constructor(id: string, type: string, group: string, layout: string, modelType: string, target: SVNode) {
|
||||||
|
super(id, type, group, layout, modelType);
|
||||||
|
|
||||||
|
this.target = target;
|
||||||
|
this.target.appendages.push(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已释放节点下面的文字(“已释放‘)
|
||||||
|
*/
|
||||||
|
export class SVFreedLabel extends SVNodeAppendage {
|
||||||
|
constructor(id: string, type: string, group: string, layout: string, target: SVNode) {
|
||||||
|
super(id, type, group, layout, 'freedLabel', target);
|
||||||
|
|
||||||
|
this.target.freedLabel = this;
|
||||||
|
this.G6ModelProps = this.generateG6ModelProps();
|
||||||
|
}
|
||||||
|
|
||||||
|
generateG6ModelProps() {
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
type: 'rect',
|
||||||
|
label: '已释放',
|
||||||
|
labelCfg: {
|
||||||
|
style: {
|
||||||
|
fill: '#b83b5e',
|
||||||
|
opacity: 0.6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
size: [0, 0],
|
||||||
|
style: {
|
||||||
|
stroke: null,
|
||||||
|
fill: 'transparent'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被移动到泄漏区的节点上面显示的地址
|
||||||
|
*/
|
||||||
|
export class SVAddressLabel extends SVNodeAppendage {
|
||||||
|
private sourceId: string;
|
||||||
|
|
||||||
|
constructor(id: string, type: string, group: string, layout: string, target: SVNode, options: AddressLabelOption) {
|
||||||
|
super(id, type, group, layout, 'addressLabel', target);
|
||||||
|
|
||||||
|
this.sourceId = target.sourceId;
|
||||||
|
this.target.addressLabel = this;
|
||||||
|
this.G6ModelProps = this.generateG6ModelProps(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
generateG6ModelProps(options: AddressLabelOption) {
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
type: 'rect',
|
||||||
|
label: this.sourceId,
|
||||||
|
labelCfg: {
|
||||||
|
style: {
|
||||||
|
fill: '#666',
|
||||||
|
fontSize: 16,
|
||||||
|
...options.style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
size: [0, 0],
|
||||||
|
style: {
|
||||||
|
stroke: null,
|
||||||
|
fill: 'transparent'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点的下标文字
|
||||||
|
*/
|
||||||
|
export class SVIndexLabel extends SVNodeAppendage {
|
||||||
|
private value: string;
|
||||||
|
|
||||||
|
constructor(id: string, indexName: string, group: string, layout: string, value: string, target: SVNode, options: IndexLabelOption) {
|
||||||
|
super(id, indexName, group, layout, 'indexLabel', target);
|
||||||
|
|
||||||
|
this.target.indexLabel = this;
|
||||||
|
this.value = value;
|
||||||
|
this.G6ModelProps = this.generateG6ModelProps(options) as NodeConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
generateG6ModelProps(options: IndexLabelOption): NodeConfig | EdgeConfig {
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
type: 'rect',
|
||||||
|
label: this.value,
|
||||||
|
labelCfg: {
|
||||||
|
style: {
|
||||||
|
fill: '#bbb',
|
||||||
|
textAlign: 'center',
|
||||||
|
textBaseline: 'middle',
|
||||||
|
fontSize: 14,
|
||||||
|
fontStyle: 'italic',
|
||||||
|
...options.style
|
||||||
|
}
|
||||||
|
},
|
||||||
|
size: [0, 0],
|
||||||
|
style: {
|
||||||
|
stroke: null,
|
||||||
|
fill: 'transparent'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部指针
|
||||||
|
*/
|
||||||
|
export class SVMarker extends SVNodeAppendage {
|
||||||
|
public label: string | string[];
|
||||||
|
public anchor: number;
|
||||||
|
|
||||||
|
public shadowG6Item: INode;
|
||||||
|
public G6Item: INode;
|
||||||
|
|
||||||
|
constructor(id: string, type: string, group: string, layout: string, label: string | string[], target: SVNode, options: MarkerOption) {
|
||||||
|
super(id, type, group, layout, 'marker', target);
|
||||||
|
|
||||||
|
this.label = label;
|
||||||
|
|
||||||
|
this.target.marker = this;
|
||||||
|
this.G6ModelProps = this.generateG6ModelProps(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
generateG6ModelProps(options: MarkerOption): NodeConfig {
|
||||||
|
this.anchor = options.anchor;
|
||||||
|
|
||||||
|
const type = options.type,
|
||||||
|
defaultSize: [number, number] = type === 'pointer' ? [8, 30] : [12, 12];
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
rotation: 0,
|
||||||
|
type: options.type || 'marker',
|
||||||
|
size: options.size || defaultSize,
|
||||||
|
anchorPoints: null,
|
||||||
|
label: typeof this.label === 'string' ? this.label : this.label.join(', '),
|
||||||
|
style: Util.objectClone<Style>(options.style),
|
||||||
|
labelCfg: Util.objectClone<NodeLabelOption>(options.labelOptions)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public getLabelSizeRadius(): number {
|
||||||
|
const { width, height } = this.shadowG6Item.getContainer().getChildren()[2].getBBox();
|
||||||
|
return width > height ? width : height;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,19 +1,20 @@
|
|||||||
import { Util } from "../Common/util";
|
import { Util } from "../Common/util";
|
||||||
import { Engine } from "../engine";
|
import { Engine } from "../engine";
|
||||||
import { LayoutCreator, LayoutGroupOptions, LinkOption, MarkerOption, NodeOption } from "../options";
|
import { AddressLabelOption, IndexLabelOption, LayoutCreator, LayoutGroupOptions, LinkOption, MarkerOption, NodeOption } from "../options";
|
||||||
import { sourceLinkData, LinkTarget, Sources, SourceNode } from "../sources";
|
import { sourceLinkData, LinkTarget, Sources, SourceNode } from "../sources";
|
||||||
import { SV } from "../StructV";
|
import { SV } from "../StructV";
|
||||||
import { SVLink } from "./SVLink";
|
import { SVLink } from "./SVLink";
|
||||||
import { SVMarker } from "./SVMarker";
|
|
||||||
import { SVModel } from "./SVModel";
|
import { SVModel } from "./SVModel";
|
||||||
import { SVFreedLabel, SVLeakAddress, SVNode } from "./SVNode";
|
import { SVNode } from "./SVNode";
|
||||||
|
import { SVAddressLabel, SVFreedLabel, SVIndexLabel, SVMarker } from "./SVNodeAppendage";
|
||||||
|
|
||||||
|
|
||||||
export type LayoutGroup = {
|
export type LayoutGroup = {
|
||||||
name: string;
|
name: string;
|
||||||
node: SVNode[];
|
node: SVNode[];
|
||||||
|
indexLabel: SVIndexLabel[];
|
||||||
freedLabel: SVFreedLabel[];
|
freedLabel: SVFreedLabel[];
|
||||||
leakAddress: SVLeakAddress[];
|
addressLabel: SVAddressLabel[];
|
||||||
link: SVLink[];
|
link: SVLink[];
|
||||||
marker: SVMarker[];
|
marker: SVMarker[];
|
||||||
layoutCreator: LayoutCreator;
|
layoutCreator: LayoutCreator;
|
||||||
@ -38,13 +39,12 @@ export class ModelConstructor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建svnode,svlink 和 svmarker
|
* 构建SVNode,SVLink, SVMarker, SVAddressLabel, SVIndexLabel等
|
||||||
* @param sourceList
|
* @param sourceList
|
||||||
*/
|
*/
|
||||||
public construct(sources: Sources): LayoutGroupTable {
|
public construct(sources: Sources): LayoutGroupTable {
|
||||||
const layoutGroupTable = new Map<string, LayoutGroup>(),
|
const layoutGroupTable = new Map<string, LayoutGroup>(),
|
||||||
layoutMap: { [key: string]: LayoutCreator } = SV.registeredLayout,
|
layoutMap: { [key: string]: LayoutCreator } = SV.registeredLayout;
|
||||||
optionsTable = this.engine.optionsTable;
|
|
||||||
|
|
||||||
Object.keys(sources).forEach(group => {
|
Object.keys(sources).forEach(group => {
|
||||||
let sourceGroup = sources[group],
|
let sourceGroup = sources[group],
|
||||||
@ -59,21 +59,25 @@ export class ModelConstructor {
|
|||||||
prevString: string = this.prevSourcesStringMap[group],
|
prevString: string = this.prevSourcesStringMap[group],
|
||||||
nodeList: SVNode[] = [],
|
nodeList: SVNode[] = [],
|
||||||
freedLabelList: SVFreedLabel[] = [],
|
freedLabelList: SVFreedLabel[] = [],
|
||||||
leakAddress: SVLeakAddress[] = [],
|
addressLabelList: SVAddressLabel[] = [],
|
||||||
|
indexLabelList: SVIndexLabel[] = [],
|
||||||
markerList: SVMarker[] = [];
|
markerList: SVMarker[] = [];
|
||||||
|
|
||||||
if (prevString === sourceDataString) {
|
if (prevString === sourceDataString) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: LayoutGroupOptions = optionsTable[layout],
|
const options: LayoutGroupOptions = layoutCreator.defineOptions(sourceGroup.data),
|
||||||
sourceData = layoutCreator.sourcesPreprocess(sourceGroup.data, options),
|
sourceData = layoutCreator.sourcesPreprocess(sourceGroup.data, options),
|
||||||
nodeOptions = options.node || options['element'] || {},
|
nodeOptions = options.node || options['element'] || {},
|
||||||
markerOptions = options.marker || {};
|
markerOptions = options.marker || {},
|
||||||
|
indexLabelOptions = options.indexLabel || {},
|
||||||
|
addressLabelOption = options.addressLabel || {};
|
||||||
|
|
||||||
nodeList = this.constructNodes(nodeOptions, group, sourceData, layout);
|
nodeList = this.constructNodes(group, layout, nodeOptions, sourceData);
|
||||||
leakAddress = nodeList.map(item => item.leakAddress);
|
|
||||||
markerList = this.constructMarkers(group, layout, markerOptions, nodeList);
|
markerList = this.constructMarkers(group, layout, markerOptions, nodeList);
|
||||||
|
indexLabelList = this.constructIndexLabel(group, layout, indexLabelOptions, nodeList);
|
||||||
|
addressLabelList = this.constructAddressLabel(group, layout, addressLabelOption, nodeList);
|
||||||
nodeList.forEach(item => {
|
nodeList.forEach(item => {
|
||||||
if(item.freedLabel) {
|
if(item.freedLabel) {
|
||||||
freedLabelList.push(item.freedLabel);
|
freedLabelList.push(item.freedLabel);
|
||||||
@ -84,12 +88,19 @@ export class ModelConstructor {
|
|||||||
name: group,
|
name: group,
|
||||||
node: nodeList,
|
node: nodeList,
|
||||||
freedLabel: freedLabelList,
|
freedLabel: freedLabelList,
|
||||||
leakAddress: leakAddress,
|
addressLabel: addressLabelList,
|
||||||
|
indexLabel: indexLabelList,
|
||||||
link: [],
|
link: [],
|
||||||
marker: markerList,
|
marker: markerList,
|
||||||
options: options,
|
options: options,
|
||||||
layoutCreator,
|
layoutCreator,
|
||||||
modelList: [...nodeList, ...markerList, ...freedLabelList, ...leakAddress],
|
modelList: [
|
||||||
|
...nodeList,
|
||||||
|
...markerList,
|
||||||
|
...freedLabelList,
|
||||||
|
...addressLabelList,
|
||||||
|
...indexLabelList
|
||||||
|
],
|
||||||
layout,
|
layout,
|
||||||
isHide: false
|
isHide: false
|
||||||
});
|
});
|
||||||
@ -97,7 +108,7 @@ export class ModelConstructor {
|
|||||||
|
|
||||||
layoutGroupTable.forEach((layoutGroup: LayoutGroup, group: string) => {
|
layoutGroupTable.forEach((layoutGroup: LayoutGroup, group: string) => {
|
||||||
const linkOptions = layoutGroup.options.link || {},
|
const linkOptions = layoutGroup.options.link || {},
|
||||||
linkList: SVLink[] = this.constructLinks(linkOptions, layoutGroup.node, layoutGroupTable, group, layoutGroup.layout, );
|
linkList: SVLink[] = this.constructLinks(group, layoutGroup.layout, linkOptions, layoutGroup.node, layoutGroupTable);
|
||||||
|
|
||||||
layoutGroup.link = linkList;
|
layoutGroup.link = linkList;
|
||||||
layoutGroup.modelList.push(...linkList);
|
layoutGroup.modelList.push(...linkList);
|
||||||
@ -108,13 +119,6 @@ export class ModelConstructor {
|
|||||||
return this.layoutGroupTable;
|
return this.layoutGroupTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
public getLayoutGroupTable(): LayoutGroupTable {
|
|
||||||
return this.layoutGroupTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从源数据构建 node 集
|
* 从源数据构建 node 集
|
||||||
@ -124,7 +128,7 @@ export class ModelConstructor {
|
|||||||
* @param layout
|
* @param layout
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
private constructNodes(nodeOptions: { [key: string]: NodeOption }, group: string, sourceList: SourceNode[], layout: string): SVNode[] {
|
private constructNodes(group: string, layout: string, nodeOptions: { [key: string]: NodeOption }, sourceList: SourceNode[]): SVNode[] {
|
||||||
let defaultSourceNodeType: string = 'default',
|
let defaultSourceNodeType: string = 'default',
|
||||||
nodeList: SVNode[] = [];
|
nodeList: SVNode[] = [];
|
||||||
|
|
||||||
@ -150,7 +154,7 @@ export class ModelConstructor {
|
|||||||
* @param layoutGroupTable
|
* @param layoutGroupTable
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
private constructLinks(linkOptions: { [key: string]: LinkOption }, nodes: SVNode[], layoutGroupTable: LayoutGroupTable, group: string, layout: string): SVLink[] {
|
private constructLinks(group: string, layout: string, linkOptions: { [key: string]: LinkOption }, nodes: SVNode[], layoutGroupTable: LayoutGroupTable): SVLink[] {
|
||||||
let linkList: SVLink[] = [],
|
let linkList: SVLink[] = [],
|
||||||
linkNames = Object.keys(linkOptions);
|
linkNames = Object.keys(linkOptions);
|
||||||
|
|
||||||
@ -197,6 +201,52 @@ export class ModelConstructor {
|
|||||||
return linkList;
|
return linkList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从配置项构建 indexLabel 集
|
||||||
|
* @param group
|
||||||
|
* @param layout
|
||||||
|
* @param indexLabelOptions
|
||||||
|
*/
|
||||||
|
private constructIndexLabel(group: string, layout: string, indexLabelOptions: { [key: string]: IndexLabelOption }, nodes: SVNode[]): SVIndexLabel[] {
|
||||||
|
let indexLabelList: SVIndexLabel[] = [],
|
||||||
|
indexNames = Object.keys(indexLabelOptions);
|
||||||
|
|
||||||
|
indexNames.forEach(name => {
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
let node = nodes[i],
|
||||||
|
value = node[name];
|
||||||
|
|
||||||
|
// 若没有指针字段的结点则跳过
|
||||||
|
if (!value) continue;
|
||||||
|
|
||||||
|
let id = `${group}.${name}#${value}`,
|
||||||
|
indexLabel = new SVIndexLabel(id, name, group, layout, value, node, indexLabelOptions[name]);
|
||||||
|
|
||||||
|
indexLabelList.push(indexLabel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return indexLabelList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param group
|
||||||
|
* @param layout
|
||||||
|
* @param addressLabelOption
|
||||||
|
* @param nodes
|
||||||
|
*/
|
||||||
|
private constructAddressLabel(group: string, layout: string, addressLabelOption: AddressLabelOption, nodes: SVNode[]): SVAddressLabel[] {
|
||||||
|
let addressLabelList: SVAddressLabel[] = [];
|
||||||
|
|
||||||
|
nodes.forEach(item => {
|
||||||
|
const addressLabel = new SVAddressLabel(`${item.id}-address-label`, item.sourceType, group, layout, item, addressLabelOption);
|
||||||
|
addressLabelList.push(addressLabel);
|
||||||
|
});
|
||||||
|
|
||||||
|
return addressLabelList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从配置和 node 集构建 marker 集
|
* 从配置和 node 集构建 marker 集
|
||||||
* @param markerOptions
|
* @param markerOptions
|
||||||
@ -216,7 +266,7 @@ export class ModelConstructor {
|
|||||||
if (!markerData) continue;
|
if (!markerData) continue;
|
||||||
|
|
||||||
let id = `${group}.${name}.${Array.isArray(markerData) ? markerData.join('-') : markerData}`,
|
let id = `${group}.${name}.${Array.isArray(markerData) ? markerData.join('-') : markerData}`,
|
||||||
marker = this.createMarker(id, name, markerData, group, layout, node, markerOptions[name]);
|
marker = new SVMarker(id, name, group, layout, markerData, node, markerOptions[name]);
|
||||||
|
|
||||||
markerList.push(marker);
|
markerList.push(marker);
|
||||||
}
|
}
|
||||||
@ -259,7 +309,6 @@ export class ModelConstructor {
|
|||||||
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);
|
||||||
node.leakAddress = new SVLeakAddress(`${id}-leak-adress`, sourceNodeType, group, layout, node);
|
|
||||||
|
|
||||||
if(node.freed) {
|
if(node.freed) {
|
||||||
node.freedLabel = new SVFreedLabel(`${id}-freed-label`, sourceNodeType, group, layout, node);
|
node.freedLabel = new SVFreedLabel(`${id}-freed-label`, sourceNodeType, group, layout, node);
|
||||||
@ -268,21 +317,6 @@ export class ModelConstructor {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 外部指针工厂,创建marker
|
|
||||||
* @param id
|
|
||||||
* @param markerName
|
|
||||||
* @param markerData
|
|
||||||
* @param group
|
|
||||||
* @param layout
|
|
||||||
* @param target
|
|
||||||
* @param options
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
private createMarker(id: string, markerName: string, markerData: string | string[], group: string, layout: string, target: SVNode, options: MarkerOption): SVMarker {
|
|
||||||
return new SVMarker(id, markerName, group, layout, markerData, target, options);;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 连线工厂,创建Link
|
* 连线工厂,创建Link
|
||||||
* @param linkName
|
* @param linkName
|
||||||
@ -388,10 +422,19 @@ export class ModelConstructor {
|
|||||||
return counter <= 2;
|
return counter <= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public getLayoutGroupTable(): LayoutGroupTable {
|
||||||
|
return this.layoutGroupTable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 销毁
|
* 销毁
|
||||||
*/
|
*/
|
||||||
destroy() {
|
destroy() {
|
||||||
this.layoutGroupTable = null;
|
this.layoutGroupTable = null;
|
||||||
|
this.prevSourcesStringMap = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
13
src/RegisteredShape/arrayNode.ts
Normal file
13
src/RegisteredShape/arrayNode.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import G6 from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
|
export default G6.registerNode('array-node', {
|
||||||
|
getAnchorPoints() {
|
||||||
|
return [
|
||||||
|
[0.5, 0],
|
||||||
|
[1, 0.5],
|
||||||
|
[0.5, 1],
|
||||||
|
[0, 0.5]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}, 'rect');
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import G6 from '@antv/g6';
|
import { registerNode } from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
export default G6.registerNode('binary-tree-node', {
|
export default registerNode('binary-tree-node', {
|
||||||
draw(cfg, group) {
|
draw(cfg, group) {
|
||||||
cfg.size = cfg.size;
|
cfg.size = cfg.size;
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ export default G6.registerNode('binary-tree-node', {
|
|||||||
height: height,
|
height: height,
|
||||||
stroke: cfg.style.stroke || '#333',
|
stroke: cfg.style.stroke || '#333',
|
||||||
cursor: cfg.style.cursor,
|
cursor: cfg.style.cursor,
|
||||||
fill: '#eee'
|
fill: cfg.style.backgroundFill || '#eee'
|
||||||
},
|
},
|
||||||
name: 'wrapper'
|
name: 'wrapper'
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import G6 from '@antv/g6';
|
import { registerNode, Util } from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
export default G6.registerNode('clen-queue-pointer', {
|
export default registerNode('clen-queue-pointer', {
|
||||||
draw(cfg, group) {
|
draw(cfg, group) {
|
||||||
let id = cfg.id as string;
|
let id = cfg.id as string;
|
||||||
|
|
||||||
@ -55,10 +55,10 @@ export default G6.registerNode('clen-queue-pointer', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// rotate(text, angle, G6.Util.transform);
|
// rotate(text, angle, G6.Util.transform);
|
||||||
translate(text, 0, -75, G6.Util.transform);
|
translate(text, 0, -75, Util.transform);
|
||||||
}
|
}
|
||||||
rotate(keyShape, angle, G6.Util.transform);
|
rotate(keyShape, angle, Util.transform);
|
||||||
translate(keyShape, 0, -75, G6.Util.transform);
|
translate(keyShape, 0, -75, Util.transform);
|
||||||
|
|
||||||
return keyShape;
|
return keyShape;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import G6 from '@antv/g6';
|
import { registerNode } from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
export default G6.registerNode('cursor', {
|
export default registerNode('cursor', {
|
||||||
draw(cfg, group) {
|
draw(cfg, group) {
|
||||||
const keyShape = group.addShape('path', {
|
const keyShape = group.addShape('path', {
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|||||||
@ -1,84 +0,0 @@
|
|||||||
import G6 from '@antv/g6';
|
|
||||||
|
|
||||||
|
|
||||||
export default G6.registerNode('indexed-node', {
|
|
||||||
draw(cfg, group) {
|
|
||||||
cfg.size = cfg.size || [30, 10];
|
|
||||||
|
|
||||||
const width = cfg.size[0],
|
|
||||||
height = cfg.size[1],
|
|
||||||
disable = cfg.disable === undefined ? false : cfg.disable;
|
|
||||||
|
|
||||||
const rect = group.addShape('rect', {
|
|
||||||
attrs: {
|
|
||||||
x: width / 2,
|
|
||||||
y: height / 2,
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
stroke: cfg.style.stroke || '#333',
|
|
||||||
fill: disable ? '#ccc' : cfg.style.fill,
|
|
||||||
cursor: cfg.style.cursor,
|
|
||||||
},
|
|
||||||
name: 'wrapper'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (cfg.label) {
|
|
||||||
const style = (cfg.labelCfg && cfg.labelCfg.style) || {};
|
|
||||||
group.addShape('text', {
|
|
||||||
attrs: {
|
|
||||||
x: width,
|
|
||||||
y: height,
|
|
||||||
textAlign: 'center',
|
|
||||||
textBaseline: 'middle',
|
|
||||||
text: cfg.label,
|
|
||||||
fill: style.fill || '#000',
|
|
||||||
fontSize: style.fontSize || 16
|
|
||||||
},
|
|
||||||
name: 'text'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const indexCfg = cfg.indexCfg;
|
|
||||||
const offset = 20;
|
|
||||||
const indexPositionMap: { [key: string]: (width: number, height: number) => { x: number, y: number } } = {
|
|
||||||
top: (width: number, height: number) => ({ x: width, y: height / 2 - offset }),
|
|
||||||
right: (width: number, height: number) => ({ x: width * 1.5 + offset, y: height }),
|
|
||||||
bottom: (width: number, height: number) => ({ x: width, y: height * 1.5 + offset }),
|
|
||||||
left: (width: number, height: number) => ({ x: width / 2 - offset, y: height })
|
|
||||||
};
|
|
||||||
|
|
||||||
if (indexCfg !== undefined) {
|
|
||||||
Object.keys(indexCfg).map(key => {
|
|
||||||
let indexCfgItem = indexCfg[key];
|
|
||||||
let position = indexCfgItem.position || 'bottom';
|
|
||||||
let { x: indexX, y: indexY } = indexPositionMap[position](width, height);
|
|
||||||
|
|
||||||
group.addShape('text', {
|
|
||||||
attrs: {
|
|
||||||
x: indexX,
|
|
||||||
y: indexY,
|
|
||||||
textAlign: 'center',
|
|
||||||
textBaseline: 'middle',
|
|
||||||
text: indexCfgItem.value.toString(),
|
|
||||||
fill: '#bbb',
|
|
||||||
fontSize: 14,
|
|
||||||
fontStyle: 'italic',
|
|
||||||
...indexCfgItem.style
|
|
||||||
},
|
|
||||||
name: 'index-text'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
},
|
|
||||||
|
|
||||||
getAnchorPoints() {
|
|
||||||
return [
|
|
||||||
[0.5, 0],
|
|
||||||
[1, 0.5],
|
|
||||||
[0.5, 1],
|
|
||||||
[0, 0.5]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import G6 from '@antv/g6';
|
import { registerNode } from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
export default G6.registerNode('link-list-node', {
|
export default registerNode('link-list-node', {
|
||||||
draw(cfg, group) {
|
draw(cfg, group) {
|
||||||
cfg.size = cfg.size || [30, 10];
|
cfg.size = cfg.size || [30, 10];
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ export default G6.registerNode('link-list-node', {
|
|||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
stroke: cfg.style.stroke || '#333',
|
stroke: cfg.style.stroke || '#333',
|
||||||
fill: '#eee',
|
fill: cfg.style.backgroundFill || '#eee',
|
||||||
cursor: cfg.style.cursor
|
cursor: cfg.style.cursor
|
||||||
},
|
},
|
||||||
name: 'wrapper'
|
name: 'wrapper'
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import G6 from '@antv/g6';
|
import { registerNode } from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
export default G6.registerNode('pointer', {
|
export default registerNode('pointer', {
|
||||||
draw(cfg, group) {
|
draw(cfg, group) {
|
||||||
const keyShape = group.addShape('path', {
|
const keyShape = group.addShape('path', {
|
||||||
attrs: {
|
attrs: {
|
||||||
@ -13,7 +13,7 @@ export default G6.registerNode('pointer', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (cfg.label) {
|
if (cfg.label) {
|
||||||
const style = (cfg.labelCfg && cfg.labelCfg.style) || {};
|
const labelStyle = (cfg.labelCfg && cfg.labelCfg.style) || {};
|
||||||
|
|
||||||
const bgRect = group.addShape('rect', {
|
const bgRect = group.addShape('rect', {
|
||||||
attrs: {
|
attrs: {
|
||||||
@ -33,8 +33,8 @@ export default G6.registerNode('pointer', {
|
|||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
textBaseline: 'middle',
|
textBaseline: 'middle',
|
||||||
text: cfg.label,
|
text: cfg.label,
|
||||||
fill: style.fill || '#999',
|
fill: labelStyle.fill || '#999',
|
||||||
fontSize: style.fontSize || 16
|
fontSize: labelStyle.fontSize || 16
|
||||||
},
|
},
|
||||||
name: 'pointer-text-shape'
|
name: 'pointer-text-shape'
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import G6 from '@antv/g6';
|
import { registerNode } from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
export default G6.registerNode('tri-tree-node', {
|
export default registerNode('tri-tree-node', {
|
||||||
draw(cfg, group) {
|
draw(cfg, group) {
|
||||||
cfg.size = cfg.size;
|
cfg.size = cfg.size;
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ export default G6.registerNode('tri-tree-node', {
|
|||||||
height: height,
|
height: height,
|
||||||
stroke: cfg.style.stroke || '#333',
|
stroke: cfg.style.stroke || '#333',
|
||||||
cursor: cfg.style.cursor,
|
cursor: cfg.style.cursor,
|
||||||
fill: '#eee'
|
fill: cfg.style.backgroundFill || '#eee'
|
||||||
},
|
},
|
||||||
name: 'wrapper'
|
name: 'wrapper'
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import G6 from '@antv/g6';
|
import { registerNode } from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default G6.registerNode('two-cell-node', {
|
export default registerNode('two-cell-node', {
|
||||||
draw(cfg, group) {
|
draw(cfg, group) {
|
||||||
cfg.size = cfg.size || [30, 10];
|
cfg.size = cfg.size || [30, 10];
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ export default G6.registerNode('two-cell-node', {
|
|||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
stroke: cfg.style.stroke,
|
stroke: cfg.style.stroke,
|
||||||
fill: '#eee'
|
fill: cfg.style.backgroundFill || '#eee'
|
||||||
},
|
},
|
||||||
name: 'wrapper'
|
name: 'wrapper'
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,21 +1,20 @@
|
|||||||
import { Engine } from "./engine";
|
import { Engine } from "./engine";
|
||||||
import { Bound } from "./Common/boundingRect";
|
import { Bound } from "./Common/boundingRect";
|
||||||
import { Group } from "./Common/group";
|
import { Group } from "./Common/group";
|
||||||
import pointer from "./RegisteredShape/pointer";
|
|
||||||
import G6, { Util } from '@antv/g6';
|
import G6, { Util } from '@antv/g6';
|
||||||
import linkListNode from "./RegisteredShape/linkListNode";
|
import Pointer from "./RegisteredShape/pointer";
|
||||||
import binaryTreeNode from "./RegisteredShape/binaryTreeNode";
|
import LinkListNode from "./RegisteredShape/linkListNode";
|
||||||
|
import BinaryTreeNode from "./RegisteredShape/binaryTreeNode";
|
||||||
import CLenQueuePointer from "./RegisteredShape/clenQueuePointer";
|
import CLenQueuePointer from "./RegisteredShape/clenQueuePointer";
|
||||||
import twoCellNode from "./RegisteredShape/twoCellNode";
|
import TwoCellNode from "./RegisteredShape/twoCellNode";
|
||||||
|
import ArrayNode from "./RegisteredShape/arrayNode";
|
||||||
import Cursor from "./RegisteredShape/cursor";
|
import Cursor from "./RegisteredShape/cursor";
|
||||||
import { Vector } from "./Common/vector";
|
import { Vector } from "./Common/vector";
|
||||||
import indexedNode from "./RegisteredShape/indexedNode";
|
|
||||||
import { EngineOptions, LayoutCreator } from "./options";
|
import { EngineOptions, LayoutCreator } from "./options";
|
||||||
import { SVNode } from "./Model/SVNode";
|
import { SVNode } from "./Model/SVNode";
|
||||||
import { SourceNode } from "./sources";
|
import { SourceNode } from "./sources";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export interface StructV {
|
export interface StructV {
|
||||||
(DOMContainer: HTMLElement, engineOptions: EngineOptions): Engine;
|
(DOMContainer: HTMLElement, engineOptions: EngineOptions): Engine;
|
||||||
Group: typeof Group;
|
Group: typeof Group;
|
||||||
@ -51,12 +50,12 @@ SV.G6 = G6;
|
|||||||
|
|
||||||
SV.registeredLayout = {};
|
SV.registeredLayout = {};
|
||||||
SV.registeredShape = [
|
SV.registeredShape = [
|
||||||
pointer,
|
Pointer,
|
||||||
linkListNode,
|
LinkListNode,
|
||||||
binaryTreeNode,
|
BinaryTreeNode,
|
||||||
twoCellNode,
|
TwoCellNode,
|
||||||
indexedNode,
|
|
||||||
Cursor,
|
Cursor,
|
||||||
|
ArrayNode,
|
||||||
CLenQueuePointer,
|
CLenQueuePointer,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { Util } from '@antv/g6';
|
import { Util, Item } from '@antv/g6';
|
||||||
|
|
||||||
|
|
||||||
export type animationConfig = {
|
export type animationConfig = {
|
||||||
duration: number;
|
duration: number;
|
||||||
timingFunction: string;
|
timingFunction: string;
|
||||||
callback?: Function;
|
callback?: () => void;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ export const Animations = {
|
|||||||
* @param G6Item
|
* @param G6Item
|
||||||
* @param animationConfig
|
* @param animationConfig
|
||||||
*/
|
*/
|
||||||
APPEND(G6Item: any, animationConfig: animationConfig) {
|
APPEND(G6Item: Item, animationConfig: animationConfig) {
|
||||||
const type = G6Item.getType(),
|
const type = G6Item.getType(),
|
||||||
group = G6Item.getContainer(),
|
group = G6Item.getContainer(),
|
||||||
Mat3 = Util.mat3,
|
Mat3 = Util.mat3,
|
||||||
@ -54,7 +54,7 @@ export const Animations = {
|
|||||||
* @param G6Item
|
* @param G6Item
|
||||||
* @param animationConfig
|
* @param animationConfig
|
||||||
*/
|
*/
|
||||||
REMOVE(G6Item: any, animationConfig: animationConfig) {
|
REMOVE(G6Item: Item, animationConfig: animationConfig) {
|
||||||
const type = G6Item.getType(),
|
const type = G6Item.getType(),
|
||||||
group = G6Item.getContainer(),
|
group = G6Item.getContainer(),
|
||||||
Mat3 = Util.mat3,
|
Mat3 = Util.mat3,
|
||||||
@ -84,7 +84,7 @@ export const Animations = {
|
|||||||
* @param G6Item
|
* @param G6Item
|
||||||
* @param animationConfig
|
* @param animationConfig
|
||||||
*/
|
*/
|
||||||
FADE_IN(G6Item: any, animationConfig: animationConfig) {
|
FADE_IN(G6Item: Item, animationConfig: animationConfig) {
|
||||||
const group = G6Item.getContainer(),
|
const group = G6Item.getContainer(),
|
||||||
animateCfg = {
|
animateCfg = {
|
||||||
duration: animationConfig.duration,
|
duration: animationConfig.duration,
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { IPoint } from '@antv/g6-core';
|
import { IPoint } from '@antv/g6-core';
|
||||||
import { Bound, BoundingRect } from '../Common/boundingRect';
|
import { Bound, BoundingRect } from '../Common/boundingRect';
|
||||||
import { Group } from '../Common/group';
|
import { Group } from '../Common/group';
|
||||||
|
import { Util } from '../Common/util';
|
||||||
import { Vector } from '../Common/vector';
|
import { Vector } from '../Common/vector';
|
||||||
import { Engine } from '../engine';
|
import { Engine } from '../engine';
|
||||||
import { LayoutGroupTable } from '../Model/modelConstructor';
|
import { LayoutGroupTable } from '../Model/modelConstructor';
|
||||||
import { SVMarker } from '../Model/SVMarker';
|
|
||||||
import { SVModel } from '../Model/SVModel';
|
import { SVModel } from '../Model/SVModel';
|
||||||
import { SVFreedLabel, SVLeakAddress, SVNode } from '../Model/SVNode';
|
import { SVAddressLabel, SVFreedLabel, SVIndexLabel, SVMarker } from '../Model/SVNodeAppendage';
|
||||||
import { LayoutOptions, MarkerOption, ViewOptions } from '../options';
|
import { AddressLabelOption, IndexLabelOption, LayoutOptions, MarkerOption, ViewOptions } from '../options';
|
||||||
import { ViewContainer } from './viewContainer';
|
import { ViewContainer } from './viewContainer';
|
||||||
|
|
||||||
|
|
||||||
@ -24,17 +24,37 @@ export class LayoutProvider {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化布局参数
|
* 布局前处理
|
||||||
* @param nodes
|
* @param layoutGroupTable
|
||||||
* @param markers
|
|
||||||
*/
|
*/
|
||||||
private initLayoutValue(nodes: SVNode[], markers: SVMarker[]) {
|
private preLayoutProcess(layoutGroupTable: LayoutGroupTable) {
|
||||||
[...nodes, ...markers].forEach(item => {
|
const modelList = Util.convertGroupTable2ModelList(layoutGroupTable);
|
||||||
|
|
||||||
|
modelList.forEach(item => {
|
||||||
|
item.preLayout = true;
|
||||||
|
|
||||||
item.set('rotation', item.get('rotation'));
|
item.set('rotation', item.get('rotation'));
|
||||||
item.set({ x: 0, y: 0 });
|
item.set({ x: 0, y: 0 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 布局后处理
|
||||||
|
* @param layoutGroupTable
|
||||||
|
*/
|
||||||
|
private postLayoutProcess(layoutGroupTable: LayoutGroupTable) {
|
||||||
|
const modelList = Util.convertGroupTable2ModelList(layoutGroupTable);
|
||||||
|
|
||||||
|
modelList.forEach(item => {
|
||||||
|
item.preLayout = false;
|
||||||
|
|
||||||
|
// 用两个变量保存节点布局完成后的坐标,因为拖拽节点会改变节点的x,y坐标
|
||||||
|
// 然后当节点移动到泄漏区的时候,不应该保持节点被拖拽后的状态,应该恢复到布局完成后的状态,不然就会很奇怪
|
||||||
|
item.layoutX = item.get('x');
|
||||||
|
item.layoutY = item.get('y');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 布局外部指针
|
* 布局外部指针
|
||||||
* @param marker
|
* @param marker
|
||||||
@ -89,7 +109,7 @@ export class LayoutProvider {
|
|||||||
*/
|
*/
|
||||||
private layoutFreedLabel(freedLabels: SVFreedLabel[]) {
|
private layoutFreedLabel(freedLabels: SVFreedLabel[]) {
|
||||||
freedLabels.forEach(item => {
|
freedLabels.forEach(item => {
|
||||||
const freedNodeBound = item.node.getBound();
|
const freedNodeBound = item.target.getBound();
|
||||||
|
|
||||||
item.set({
|
item.set({
|
||||||
x: freedNodeBound.x + freedNodeBound.width / 2,
|
x: freedNodeBound.x + freedNodeBound.width / 2,
|
||||||
@ -99,18 +119,64 @@ export class LayoutProvider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param indexLabels
|
||||||
|
* @param indexLabelOptions
|
||||||
|
*/
|
||||||
|
private layoutIndexLabel(indexLabels: SVIndexLabel[], indexLabelOptions: { [key: string]: IndexLabelOption }) {
|
||||||
|
const indexLabelPositionMap: { [key: string]: (nodeBound: BoundingRect, labelBound: BoundingRect, offset: number) => { x: number, y: number } } = {
|
||||||
|
top: (nodeBound: BoundingRect, labelBound: BoundingRect, offset: number) => {
|
||||||
|
return {
|
||||||
|
x: nodeBound.x + nodeBound.width / 2,
|
||||||
|
y: nodeBound.y - offset
|
||||||
|
};
|
||||||
|
},
|
||||||
|
right: (nodeBound: BoundingRect, labelBound: BoundingRect, offset: number) => {
|
||||||
|
return {
|
||||||
|
x: nodeBound.x + nodeBound.width + offset,
|
||||||
|
y: nodeBound.y + nodeBound.height / 2
|
||||||
|
};
|
||||||
|
},
|
||||||
|
bottom: (nodeBound: BoundingRect, labelBound: BoundingRect, offset: number) => {
|
||||||
|
return {
|
||||||
|
x: nodeBound.x + nodeBound.width / 2,
|
||||||
|
y: nodeBound.y + nodeBound.height + offset
|
||||||
|
};
|
||||||
|
},
|
||||||
|
left: (nodeBound: BoundingRect, labelBound: BoundingRect, offset: number) => {
|
||||||
|
return {
|
||||||
|
x: nodeBound.x - labelBound.width - 2 * offset,
|
||||||
|
y: nodeBound.y + nodeBound.height / 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
indexLabels.forEach(item => {
|
||||||
|
const options: IndexLabelOption = indexLabelOptions[item.sourceType],
|
||||||
|
nodeBound = item.target.getBound(),
|
||||||
|
labelBound = item.getBound(),
|
||||||
|
offset = options.offset ?? 20,
|
||||||
|
position = options.position ?? 'bottom';
|
||||||
|
|
||||||
|
const pos = indexLabelPositionMap[position](nodeBound, labelBound, offset);
|
||||||
|
item.set(pos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 布局泄漏区节点上面的address label
|
* 布局泄漏区节点上面的address label
|
||||||
* @param leakAddress
|
* @param leakAddress
|
||||||
*/
|
*/
|
||||||
private layoutLeakAddress(leakAddress: SVLeakAddress[]) {
|
private layoutAddressLabel(leakAddress: SVAddressLabel[], addressLabelOption: AddressLabelOption) {
|
||||||
|
const offset = addressLabelOption.offset || 16;
|
||||||
|
|
||||||
leakAddress.forEach(item => {
|
leakAddress.forEach(item => {
|
||||||
const nodeBound = item.node.getBound();
|
const nodeBound = item.target.getBound();
|
||||||
|
|
||||||
item.set({
|
item.set({
|
||||||
x: nodeBound.x + nodeBound.width / 2,
|
x: nodeBound.x + nodeBound.width / 2,
|
||||||
y: nodeBound.y - 16,
|
y: nodeBound.y - offset
|
||||||
size: [nodeBound.width, 0]
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -124,23 +190,28 @@ export class LayoutProvider {
|
|||||||
const modelGroupList: Group[] = [];
|
const modelGroupList: Group[] = [];
|
||||||
|
|
||||||
layoutGroupTable.forEach(group => {
|
layoutGroupTable.forEach(group => {
|
||||||
const options: LayoutOptions = group.options.layout,
|
const modelList: SVModel[] = group.modelList,
|
||||||
modelList: SVModel[] = group.modelList,
|
|
||||||
modelGroup: Group = new Group();
|
modelGroup: Group = new Group();
|
||||||
|
|
||||||
|
const layoutOptions: LayoutOptions = group.options.layout;
|
||||||
|
|
||||||
modelList.forEach(item => {
|
modelList.forEach(item => {
|
||||||
modelGroup.add(item);
|
modelGroup.add(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.initLayoutValue(group.node, group.marker); // 初始化布局参数
|
group.layoutCreator.layout(group.node, layoutOptions); // 布局节点
|
||||||
group.layoutCreator.layout(group.node, options); // 布局节点
|
|
||||||
modelGroupList.push(modelGroup);
|
modelGroupList.push(modelGroup);
|
||||||
});
|
});
|
||||||
|
|
||||||
layoutGroupTable.forEach(group => {
|
layoutGroupTable.forEach(group => {
|
||||||
|
const markerOptions = group.options.marker || {},
|
||||||
|
indexLabelOptions = group.options.indexLabel || {},
|
||||||
|
addressLabelOption = group.options.addressLabel || {};
|
||||||
|
|
||||||
|
this.layoutIndexLabel(group.indexLabel, indexLabelOptions);
|
||||||
this.layoutFreedLabel(group.freedLabel);
|
this.layoutFreedLabel(group.freedLabel);
|
||||||
this.layoutLeakAddress(group.leakAddress);
|
this.layoutAddressLabel(group.addressLabel, addressLabelOption);
|
||||||
this.layoutMarker(group.marker, group.options.marker); // 布局外部指针
|
this.layoutMarker(group.marker, markerOptions); // 布局外部指针
|
||||||
});
|
});
|
||||||
|
|
||||||
return modelGroupList;
|
return modelGroupList;
|
||||||
@ -154,10 +225,17 @@ export class LayoutProvider {
|
|||||||
private layoutLeakModels(leakModels: SVModel[], accumulateLeakModels: SVModel[]) {
|
private layoutLeakModels(leakModels: SVModel[], accumulateLeakModels: SVModel[]) {
|
||||||
const group: Group = new Group(),
|
const group: Group = new Group(),
|
||||||
containerHeight = this.viewContainer.getG6Instance().getHeight(),
|
containerHeight = this.viewContainer.getG6Instance().getHeight(),
|
||||||
leakAreaHeightRatio = this.engine.viewOptions.leakAreaHeight,
|
leakAreaHeight = this.engine.viewOptions.leakAreaHeight,
|
||||||
leakAreaY = containerHeight * (1 - leakAreaHeightRatio),
|
leakAreaY = containerHeight - leakAreaHeight,
|
||||||
xOffset = 50;
|
xOffset = 50;
|
||||||
|
|
||||||
|
leakModels.forEach(item => {
|
||||||
|
item.set({
|
||||||
|
x: item.layoutX,
|
||||||
|
y: item.layoutY
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
group.add(...leakModels);
|
group.add(...leakModels);
|
||||||
const currentLeakGroupBound: BoundingRect = group.getBound(),
|
const currentLeakGroupBound: BoundingRect = group.getBound(),
|
||||||
globalLeakGroupBound: BoundingRect = accumulateLeakModels.length ?
|
globalLeakGroupBound: BoundingRect = accumulateLeakModels.length ?
|
||||||
@ -181,8 +259,7 @@ export class LayoutProvider {
|
|||||||
prevBound: BoundingRect,
|
prevBound: BoundingRect,
|
||||||
bound: BoundingRect,
|
bound: BoundingRect,
|
||||||
boundList: BoundingRect[] = [],
|
boundList: BoundingRect[] = [],
|
||||||
maxHeight: number = -Infinity,
|
dx = 0;
|
||||||
dx = 0, dy = 0;
|
|
||||||
|
|
||||||
// 左往右布局
|
// 左往右布局
|
||||||
for (let i = 0; i < modelGroupList.length; i++) {
|
for (let i = 0; i < modelGroupList.length; i++) {
|
||||||
@ -196,10 +273,6 @@ export class LayoutProvider {
|
|||||||
dx = bound.x;
|
dx = bound.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bound.height > maxHeight) {
|
|
||||||
maxHeight = bound.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
group.translate(dx, 0);
|
group.translate(dx, 0);
|
||||||
Bound.translate(bound, dx, 0);
|
Bound.translate(bound, dx, 0);
|
||||||
boundList.push(bound);
|
boundList.push(bound);
|
||||||
@ -207,16 +280,6 @@ export class LayoutProvider {
|
|||||||
prevBound = bound;
|
prevBound = bound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 居中对齐布局
|
|
||||||
for (let i = 0; i < modelGroupList.length; i++) {
|
|
||||||
group = modelGroupList[i];
|
|
||||||
bound = boundList[i];
|
|
||||||
|
|
||||||
dy = maxHeight / 2 - bound.height / 2;
|
|
||||||
group.translate(0, dy);
|
|
||||||
Bound.translate(bound, 0, dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrapperGroup;
|
return wrapperGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,10 +292,10 @@ export class LayoutProvider {
|
|||||||
private fitCenter(group: Group) {
|
private fitCenter(group: Group) {
|
||||||
let width = this.viewContainer.getG6Instance().getWidth(),
|
let width = this.viewContainer.getG6Instance().getWidth(),
|
||||||
height = this.viewContainer.getG6Instance().getHeight(),
|
height = this.viewContainer.getG6Instance().getHeight(),
|
||||||
leakAreaHeightRatio = this.engine.viewOptions.leakAreaHeight;
|
leakAreaHeight = this.engine.viewOptions.leakAreaHeight;
|
||||||
|
|
||||||
if (this.viewContainer.hasLeak) {
|
if (this.viewContainer.hasLeak) {
|
||||||
height = height * (1 - leakAreaHeightRatio);
|
height = height - leakAreaHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewBound: BoundingRect = group.getBound(),
|
const viewBound: BoundingRect = group.getBound(),
|
||||||
@ -245,20 +308,26 @@ export class LayoutProvider {
|
|||||||
group.translate(dx, dy);
|
group.translate(dx, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 布局
|
* 布局
|
||||||
* @param layoutGroupTable
|
* @param layoutGroupTable
|
||||||
* @param leakModels
|
* @param leakModels
|
||||||
* @param hasLeak
|
* @param hasLeak
|
||||||
|
* @param needFitCenter
|
||||||
*/
|
*/
|
||||||
public layoutAll(layoutGroupTable: LayoutGroupTable, accumulateLeakModels: SVModel[], leakModels: SVModel[]) {
|
public layoutAll(layoutGroupTable: LayoutGroupTable, accumulateLeakModels: SVModel[], leakModels: SVModel[]) {
|
||||||
|
this.preLayoutProcess(layoutGroupTable);
|
||||||
|
|
||||||
const modelGroupList: Group[] = this.layoutModels(layoutGroupTable);
|
const modelGroupList: Group[] = this.layoutModels(layoutGroupTable);
|
||||||
const globalGroup: Group = this.layoutGroups(modelGroupList);
|
const generalGroup: Group = this.layoutGroups(modelGroupList);
|
||||||
|
|
||||||
if (leakModels.length) {
|
if (leakModels.length) {
|
||||||
this.layoutLeakModels(leakModels, accumulateLeakModels);
|
this.layoutLeakModels(leakModels, accumulateLeakModels);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fitCenter(globalGroup);
|
this.fitCenter(generalGroup);
|
||||||
|
this.postLayoutProcess(layoutGroupTable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,9 +2,9 @@ import { EventBus } from "../Common/eventBus";
|
|||||||
import { Util } from "../Common/util";
|
import { Util } from "../Common/util";
|
||||||
import { Engine } from "../engine";
|
import { Engine } from "../engine";
|
||||||
import { SVLink } from "../Model/SVLink";
|
import { SVLink } from "../Model/SVLink";
|
||||||
import { SVMarker } from "../Model/SVMarker";
|
|
||||||
import { SVModel } from "../Model/SVModel";
|
import { SVModel } from "../Model/SVModel";
|
||||||
import { SVLeakAddress, SVNode } from "../Model/SVNode";
|
import { SVNode } from "../Model/SVNode";
|
||||||
|
import { SVAddressLabel, SVMarker, SVNodeAppendage } from "../Model/SVNodeAppendage";
|
||||||
import { Animations } from "./animation";
|
import { Animations } from "./animation";
|
||||||
import { Renderer } from "./renderer";
|
import { Renderer } from "./renderer";
|
||||||
|
|
||||||
@ -81,18 +81,10 @@ export class Reconcile {
|
|||||||
item.leaked = true;
|
item.leaked = true;
|
||||||
leakModels.push(item);
|
leakModels.push(item);
|
||||||
|
|
||||||
if (item.marker) {
|
item.appendages.forEach(appendage => {
|
||||||
item.marker.leaked = true;
|
appendage.leaked = true;
|
||||||
leakModels.push(item.marker);
|
leakModels.push(appendage);
|
||||||
}
|
});
|
||||||
|
|
||||||
if(item.freedLabel) {
|
|
||||||
item.marker.leaked = true;
|
|
||||||
leakModels.push(item.freedLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
item.leakAddress.leaked = true;
|
|
||||||
leakModels.push(item.leakAddress);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -219,9 +211,19 @@ export class Reconcile {
|
|||||||
let { duration, timingFunction } = this.engine.animationOptions;
|
let { duration, timingFunction } = this.engine.animationOptions;
|
||||||
|
|
||||||
appendModels.forEach(item => {
|
appendModels.forEach(item => {
|
||||||
if(item instanceof SVLeakAddress) {
|
if (item instanceof SVNodeAppendage) {
|
||||||
const leakAddressG6Group = item.G6Item.getContainer();
|
// 先不显示泄漏区节点上面的地址文本
|
||||||
leakAddressG6Group.attr({ opacity: 0 });
|
if (item instanceof SVAddressLabel) {
|
||||||
|
// 先将透明度改为0,隐藏掉
|
||||||
|
const AddressLabelG6Group = item.G6Item.getContainer();
|
||||||
|
AddressLabelG6Group.attr({ opacity: 0 });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Animations.FADE_IN(item.G6Item, {
|
||||||
|
duration,
|
||||||
|
timingFunction
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Animations.APPEND(item.G6Item, {
|
Animations.APPEND(item.G6Item, {
|
||||||
@ -258,7 +260,7 @@ export class Reconcile {
|
|||||||
let { duration, timingFunction } = this.engine.animationOptions;
|
let { duration, timingFunction } = this.engine.animationOptions;
|
||||||
|
|
||||||
leakModels.forEach(item => {
|
leakModels.forEach(item => {
|
||||||
if(item instanceof SVLeakAddress) {
|
if (item instanceof SVAddressLabel) {
|
||||||
Animations.FADE_IN(item.G6Item, {
|
Animations.FADE_IN(item.G6Item, {
|
||||||
duration,
|
duration,
|
||||||
timingFunction
|
timingFunction
|
||||||
@ -387,6 +389,8 @@ export class Reconcile {
|
|||||||
ACCUMULATE_LEAK
|
ACCUMULATE_LEAK
|
||||||
} = diffResult;
|
} = diffResult;
|
||||||
|
|
||||||
|
this.handleAccumulateLeakModels(ACCUMULATE_LEAK);
|
||||||
|
|
||||||
// 第一次渲染的时候不高亮变化的元素
|
// 第一次渲染的时候不高亮变化的元素
|
||||||
if (this.isFirstPatch === false) {
|
if (this.isFirstPatch === false) {
|
||||||
this.handleChangeModels(UPDATE);
|
this.handleChangeModels(UPDATE);
|
||||||
@ -397,10 +401,11 @@ export class Reconcile {
|
|||||||
this.handleAppendModels(APPEND);
|
this.handleAppendModels(APPEND);
|
||||||
this.handleLeakModels(LEAKED);
|
this.handleLeakModels(LEAKED);
|
||||||
this.handleRemoveModels(REMOVE);
|
this.handleRemoveModels(REMOVE);
|
||||||
this.handleAccumulateLeakModels(ACCUMULATE_LEAK);
|
|
||||||
|
|
||||||
if (this.isFirstPatch) {
|
if (this.isFirstPatch) {
|
||||||
this.isFirstPatch = false;
|
this.isFirstPatch = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public destroy() { }
|
||||||
}
|
}
|
||||||
@ -1,9 +1,8 @@
|
|||||||
import { Engine } from '../engine';
|
import { Engine } from '../engine';
|
||||||
import { SVModel } from '../Model/SVModel';
|
import { SVModel } from '../Model/SVModel';
|
||||||
import { Util } from '../Common/util';
|
import { Util } from '../Common/util';
|
||||||
import G6 from '@antv/g6';
|
import { Tooltip, Graph, GraphData } from '@antv/g6';
|
||||||
import { InitViewBehaviors } from '../BehaviorHelper/initViewBehaviors';
|
import { InitViewBehaviors } from '../BehaviorHelper/initViewBehaviors';
|
||||||
import { Graph, GraphData, IGroup } from '@antv/g6-pc';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ export class Renderer {
|
|||||||
duration: number = this.engine.animationOptions.duration,
|
duration: number = this.engine.animationOptions.duration,
|
||||||
timingFunction: string = this.engine.animationOptions.timingFunction;
|
timingFunction: string = this.engine.animationOptions.timingFunction;
|
||||||
|
|
||||||
const tooltip = new G6.Tooltip({
|
const tooltip = new Tooltip({
|
||||||
offsetX: 10,
|
offsetX: 10,
|
||||||
offsetY: 20,
|
offsetY: 20,
|
||||||
shouldBegin(event) {
|
shouldBegin(event) {
|
||||||
@ -38,12 +37,12 @@ export class Renderer {
|
|||||||
itemTypes: ['node']
|
itemTypes: ['node']
|
||||||
});
|
});
|
||||||
|
|
||||||
this.shadowG6Instance = new G6.Graph({
|
this.shadowG6Instance = new Graph({
|
||||||
container: DOMContainer.cloneNode() as HTMLElement
|
container: DOMContainer.cloneNode() as HTMLElement
|
||||||
});
|
});
|
||||||
|
|
||||||
// 初始化g6实例
|
// 初始化g6实例
|
||||||
this.g6Instance = new G6.Graph({
|
this.g6Instance = new Graph({
|
||||||
container: DOMContainer,
|
container: DOMContainer,
|
||||||
width: DOMContainer.offsetWidth,
|
width: DOMContainer.offsetWidth,
|
||||||
height: DOMContainer.offsetHeight,
|
height: DOMContainer.offsetHeight,
|
||||||
@ -55,7 +54,7 @@ export class Renderer {
|
|||||||
},
|
},
|
||||||
fitView: false,
|
fitView: false,
|
||||||
modes: {
|
modes: {
|
||||||
default: InitViewBehaviors(this.engine.optionsTable)
|
default: InitViewBehaviors()
|
||||||
},
|
},
|
||||||
plugins: [tooltip]
|
plugins: [tooltip]
|
||||||
});
|
});
|
||||||
@ -97,6 +96,7 @@ export class Renderer {
|
|||||||
this.shadowG6Instance.read(g6Data);
|
this.shadowG6Instance.read(g6Data);
|
||||||
renderModelList.forEach(item => {
|
renderModelList.forEach(item => {
|
||||||
item.shadowG6Item = this.shadowG6Instance.findById(item.id);
|
item.shadowG6Item = this.shadowG6Instance.findById(item.id);
|
||||||
|
item.shadowG6Instance = this.shadowG6Instance;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,9 +111,13 @@ export class Renderer {
|
|||||||
this.g6Instance.changeData(renderData);
|
this.g6Instance.changeData(renderData);
|
||||||
|
|
||||||
renderModelList.forEach(item => {
|
renderModelList.forEach(item => {
|
||||||
|
item.g6Instance = this.g6Instance;
|
||||||
item.G6Item = this.g6Instance.findById(item.id);
|
item.G6Item = this.g6Instance.findById(item.id);
|
||||||
item.G6Item['SVModel'] = item;
|
item.G6Item['SVModel'] = item;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.g6Instance.getEdges().forEach(item => item.toFront());
|
||||||
|
this.g6Instance.paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,6 +136,24 @@ export class Renderer {
|
|||||||
return this.g6Instance;
|
return this.g6Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public refresh() {
|
||||||
|
this.g6Instance.refresh();
|
||||||
|
this.shadowG6Instance.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param width
|
||||||
|
* @param height
|
||||||
|
*/
|
||||||
|
public changeSize(width: number, height: number) {
|
||||||
|
this.g6Instance.changeSize(width, height);
|
||||||
|
this.shadowG6Instance.changeSize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 销毁
|
* 销毁
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -8,7 +8,9 @@ import { Reconcile } from "./reconcile";
|
|||||||
import { FixNodeMarkerDrag } from "../BehaviorHelper/fixNodeMarkerDrag";
|
import { FixNodeMarkerDrag } from "../BehaviorHelper/fixNodeMarkerDrag";
|
||||||
import { InitDragCanvasWithLeak } from "../BehaviorHelper/dragCanvasWithLeak";
|
import { InitDragCanvasWithLeak } from "../BehaviorHelper/dragCanvasWithLeak";
|
||||||
import { EventBus } from "../Common/eventBus";
|
import { EventBus } from "../Common/eventBus";
|
||||||
|
import { InitZoomCanvasWithLeak } from "../BehaviorHelper/zoomCanvasWithLeak";
|
||||||
import { Group } from "../Common/group";
|
import { Group } from "../Common/group";
|
||||||
|
import { Graph } from "_@antv_g6-pc@0.5.0@@antv/g6-pc";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -40,17 +42,17 @@ export class ViewContainer {
|
|||||||
height = this.getG6Instance().getHeight(),
|
height = this.getG6Instance().getHeight(),
|
||||||
{ drag, zoom } = this.engine.interactionOptions;
|
{ drag, zoom } = this.engine.interactionOptions;
|
||||||
|
|
||||||
this.leakAreaY = height * (1 - leakAreaHeight);
|
this.leakAreaY = height - leakAreaHeight;
|
||||||
|
|
||||||
if (drag) {
|
if (drag) {
|
||||||
InitDragCanvasWithLeak(this);
|
InitDragCanvasWithLeak(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zoom) {
|
if (zoom) {
|
||||||
// InitZoomCanvas(g6Instance, g6GeneralGroup);
|
// InitZoomCanvasWithLeak(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
FixNodeMarkerDrag(g6Instance, this.engine.optionsTable);
|
FixNodeMarkerDrag(g6Instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -60,17 +62,37 @@ export class ViewContainer {
|
|||||||
* 对主视图进行重新布局
|
* 对主视图进行重新布局
|
||||||
*/
|
*/
|
||||||
reLayout() {
|
reLayout() {
|
||||||
this.layoutProvider.layoutAll(this.prevLayoutGroupTable, [], this.accumulateLeakModels);
|
const g6Instance = this.getG6Instance(),
|
||||||
|
group = g6Instance.getGroup(),
|
||||||
|
matrix = group.getMatrix();
|
||||||
|
|
||||||
|
if (matrix) {
|
||||||
|
let dx = matrix[6],
|
||||||
|
dy = matrix[7];
|
||||||
|
|
||||||
|
g6Instance.translate(-dx, -dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.layoutProvider.layoutAll(this.prevLayoutGroupTable, this.accumulateLeakModels, []);
|
||||||
|
g6Instance.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 g6 实例
|
* 获取 g6 实例
|
||||||
*/
|
*/
|
||||||
getG6Instance() {
|
getG6Instance(): Graph {
|
||||||
return this.renderer.getG6Instance();
|
return this.renderer.getG6Instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取泄漏区里面的元素
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
getAccumulateLeakModels(): SVModel[] {
|
||||||
|
return this.accumulateLeakModels;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新视图
|
* 刷新视图
|
||||||
*/
|
*/
|
||||||
@ -84,17 +106,20 @@ export class ViewContainer {
|
|||||||
* @param height
|
* @param height
|
||||||
*/
|
*/
|
||||||
resize(width: number, height: number) {
|
resize(width: number, height: number) {
|
||||||
this.renderer.getG6Instance().changeSize(width, height);
|
const g6Instance = this.getG6Instance(),
|
||||||
|
prevContainerHeight = g6Instance.getHeight(),
|
||||||
|
globalGroup: Group = new Group();
|
||||||
|
|
||||||
const containerHeight = this.getG6Instance().getHeight(),
|
globalGroup.add(...this.prevModelList, ...this.accumulateLeakModels);
|
||||||
leakAreaHeight = this.engine.viewOptions.leakAreaHeight,
|
this.renderer.changeSize(width, height);
|
||||||
targetY = containerHeight * (1 - leakAreaHeight);
|
|
||||||
|
|
||||||
const accumulateLeakGroup = new Group();
|
const containerHeight = g6Instance.getHeight(),
|
||||||
accumulateLeakGroup.add(...this.accumulateLeakModels);
|
dy = containerHeight - prevContainerHeight;
|
||||||
accumulateLeakGroup.translate(0, targetY - this.leakAreaY);
|
|
||||||
this.leakAreaY = targetY;
|
|
||||||
|
|
||||||
|
globalGroup.translate(0, dy);
|
||||||
|
this.renderer.refresh();
|
||||||
|
|
||||||
|
this.leakAreaY += dy;
|
||||||
EventBus.emit('onLeakAreaUpdate', {
|
EventBus.emit('onLeakAreaUpdate', {
|
||||||
leakAreaY: this.leakAreaY,
|
leakAreaY: this.leakAreaY,
|
||||||
hasLeak: this.hasLeak
|
hasLeak: this.hasLeak
|
||||||
@ -144,10 +169,6 @@ export class ViewContainer {
|
|||||||
|
|
||||||
this.prevLayoutGroupTable = layoutGroupTable;
|
this.prevLayoutGroupTable = layoutGroupTable;
|
||||||
this.prevModelList = modelList;
|
this.prevModelList = modelList;
|
||||||
|
|
||||||
// modelList.forEach(item => {
|
|
||||||
// console.log(item.getModelType(), item.getBound());
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,6 +176,11 @@ export class ViewContainer {
|
|||||||
*/
|
*/
|
||||||
destroy() {
|
destroy() {
|
||||||
this.renderer.destroy();
|
this.renderer.destroy();
|
||||||
|
this.reconcile.destroy();
|
||||||
|
this.layoutProvider = null;
|
||||||
|
this.prevLayoutGroupTable = null;
|
||||||
|
this.prevModelList.length = 0;
|
||||||
|
this.accumulateLeakModels.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -162,15 +188,9 @@ export class ViewContainer {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 把渲染前要触发的逻辑放在这里
|
* 把渲染后要触发的逻辑放在这里
|
||||||
*/
|
*/
|
||||||
private afterRender() {
|
private afterRender() {
|
||||||
const g6Instance = this.renderer.getG6Instance();
|
|
||||||
|
|
||||||
// 把所有连线置顶
|
|
||||||
g6Instance.getEdges().forEach(item => item.toFront());
|
|
||||||
g6Instance.paint();
|
|
||||||
|
|
||||||
this.prevModelList.forEach(item => {
|
this.prevModelList.forEach(item => {
|
||||||
if (item.leaked === false) {
|
if (item.leaked === false) {
|
||||||
item.discarded = true;
|
item.discarded = true;
|
||||||
@ -179,11 +199,9 @@ export class ViewContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 把渲染后要触发的逻辑放在这里
|
* 把渲染前要触发的逻辑放在这里
|
||||||
*/
|
*/
|
||||||
private beforeRender() {
|
private beforeRender() { }
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
171
src/engine.ts
171
src/engine.ts
@ -1,35 +1,32 @@
|
|||||||
import { Sources } from "./sources";
|
import { Sources } from "./sources";
|
||||||
import { ModelConstructor } from "./Model/modelConstructor";
|
import { ModelConstructor } from "./Model/modelConstructor";
|
||||||
import { AnimationOptions, EngineOptions, InteractionOptions, LayoutGroupOptions, ViewOptions } from "./options";
|
import { AnimationOptions, EngineOptions, InteractionOptions, LayoutGroupOptions, LayoutOptions, ViewOptions } from "./options";
|
||||||
import { SV } from "./StructV";
|
|
||||||
import { EventBus } from "./Common/eventBus";
|
import { EventBus } from "./Common/eventBus";
|
||||||
import { ViewContainer } from "./View/viewContainer";
|
import { ViewContainer } from "./View/viewContainer";
|
||||||
import { SVLink } from "./Model/SVLink";
|
|
||||||
import { SVNode } from "./Model/SVNode";
|
import { SVNode } from "./Model/SVNode";
|
||||||
import { SVMarker } from "./Model/SVMarker";
|
import { Util } from "./Common/util";
|
||||||
|
import { SVModel } from "./Model/SVModel";
|
||||||
|
|
||||||
|
|
||||||
export class Engine {
|
export class Engine {
|
||||||
private modelConstructor: ModelConstructor;
|
private modelConstructor: ModelConstructor;
|
||||||
private viewContainer: ViewContainer
|
private viewContainer: ViewContainer;
|
||||||
private prevStringSourceData: string;
|
private prevSource: Sources;
|
||||||
|
private prevStringSource: string;
|
||||||
|
|
||||||
public engineOptions: EngineOptions;
|
public engineOptions: EngineOptions;
|
||||||
public viewOptions: ViewOptions;
|
public viewOptions: ViewOptions;
|
||||||
public animationOptions: AnimationOptions;
|
public animationOptions: AnimationOptions;
|
||||||
public interactionOptions: InteractionOptions;
|
public interactionOptions: InteractionOptions;
|
||||||
|
|
||||||
public optionsTable: { [key: string]: LayoutGroupOptions };
|
|
||||||
|
|
||||||
constructor(DOMContainer: HTMLElement, engineOptions: EngineOptions) {
|
constructor(DOMContainer: HTMLElement, engineOptions: EngineOptions) {
|
||||||
this.optionsTable = {};
|
|
||||||
this.engineOptions = Object.assign({}, engineOptions);
|
this.engineOptions = Object.assign({}, engineOptions);
|
||||||
|
|
||||||
this.viewOptions = Object.assign({
|
this.viewOptions = Object.assign({
|
||||||
fitCenter: true,
|
fitCenter: true,
|
||||||
fitView: false,
|
fitView: false,
|
||||||
groupPadding: 20,
|
groupPadding: 20,
|
||||||
leakAreaHeight: 0.3,
|
leakAreaHeight: 150,
|
||||||
updateHighlight: '#fc5185'
|
updateHighlight: '#fc5185'
|
||||||
}, engineOptions.view);
|
}, engineOptions.view);
|
||||||
|
|
||||||
@ -46,62 +43,41 @@ export class Engine {
|
|||||||
selectNode: true
|
selectNode: true
|
||||||
}, engineOptions.interaction);
|
}, engineOptions.interaction);
|
||||||
|
|
||||||
// 初始化布局器配置项
|
|
||||||
Object.keys(SV.registeredLayout).forEach(layout => {
|
|
||||||
if(this.optionsTable[layout] === undefined) {
|
|
||||||
const options: LayoutGroupOptions = SV.registeredLayout[layout].defineOptions();
|
|
||||||
this.optionsTable[layout] = options;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.modelConstructor = new ModelConstructor(this);
|
this.modelConstructor = new ModelConstructor(this);
|
||||||
this.viewContainer = new ViewContainer(this, DOMContainer);
|
this.viewContainer = new ViewContainer(this, DOMContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入数据进行渲染
|
* 输入数据进行渲染
|
||||||
* @param sourcesData
|
* @param sources
|
||||||
|
* @param force
|
||||||
*/
|
*/
|
||||||
public render(sourceData: Sources) {
|
public render(source: Sources, force: boolean = false) {
|
||||||
if(sourceData === undefined || sourceData === null) {
|
if (source === undefined || source === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
``
|
||||||
|
let stringSource = JSON.stringify(source);
|
||||||
|
if (force === false && this.prevStringSource === stringSource) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.viewContainer.getG6Instance().isAnimating()) {
|
this.prevSource = source;
|
||||||
return;
|
this.prevStringSource = stringSource;
|
||||||
}
|
|
||||||
|
|
||||||
let stringSourceData = JSON.stringify(sourceData);
|
|
||||||
if(this.prevStringSourceData === stringSourceData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.prevStringSourceData = stringSourceData;
|
|
||||||
|
|
||||||
// 1 转换模型(data => model)
|
// 1 转换模型(data => model)
|
||||||
const layoutGroupTable = this.modelConstructor.construct(sourceData);
|
const layoutGroupTable = this.modelConstructor.construct(source);
|
||||||
|
|
||||||
// 2 渲染(使用g6进行渲染)
|
// 2 渲染(使用g6进行渲染)
|
||||||
this.viewContainer.render(layoutGroupTable);
|
this.viewContainer.render(layoutGroupTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重新布局
|
* 重新布局
|
||||||
*/
|
*/
|
||||||
public reLayout() {
|
public reLayout() {
|
||||||
this.viewContainer.reLayout();
|
this.viewContainer.reLayout();
|
||||||
|
|
||||||
// layoutGroupTable.forEach(group => {
|
|
||||||
// group.modelList.forEach(item => {
|
|
||||||
// if(item instanceof SVLink) return;
|
|
||||||
|
|
||||||
// let model = item.G6Item.getModel(),
|
|
||||||
// x = item.get('x'),
|
|
||||||
// y = item.get('y');
|
|
||||||
|
|
||||||
// model.x = x;
|
|
||||||
// model.y = y;
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,63 +87,6 @@ export class Engine {
|
|||||||
return this.viewContainer.getG6Instance();
|
return this.viewContainer.getG6Instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有 element
|
|
||||||
* @param group
|
|
||||||
*/
|
|
||||||
public getNodes(group?: string): SVNode[] {
|
|
||||||
const layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
|
|
||||||
|
|
||||||
if(group && layoutGroupTable.has('group')) {
|
|
||||||
return layoutGroupTable.get('group').node;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nodes: SVNode[] = [];
|
|
||||||
layoutGroupTable.forEach(item => {
|
|
||||||
nodes.push(...item.node);
|
|
||||||
})
|
|
||||||
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有 marker
|
|
||||||
* @param group
|
|
||||||
*/
|
|
||||||
public getMarkers(group?: string): SVMarker[] {
|
|
||||||
const layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
|
|
||||||
|
|
||||||
if(group && layoutGroupTable.has('group')) {
|
|
||||||
return layoutGroupTable.get('group').marker;
|
|
||||||
}
|
|
||||||
|
|
||||||
const markers: SVMarker[] = [];
|
|
||||||
layoutGroupTable.forEach(item => {
|
|
||||||
markers.push(...item.marker);
|
|
||||||
})
|
|
||||||
|
|
||||||
return markers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有 link
|
|
||||||
* @param group
|
|
||||||
*/
|
|
||||||
public getLinks(group?: string): SVLink[] {
|
|
||||||
const layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
|
|
||||||
|
|
||||||
if(group && layoutGroupTable.has('group')) {
|
|
||||||
return layoutGroupTable.get('group').link;
|
|
||||||
}
|
|
||||||
|
|
||||||
const links: SVLink[] = [];
|
|
||||||
layoutGroupTable.forEach(item => {
|
|
||||||
links.push(...item.link);
|
|
||||||
})
|
|
||||||
|
|
||||||
return links;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 隐藏某些组
|
* 隐藏某些组
|
||||||
* @param groupNames
|
* @param groupNames
|
||||||
@ -192,16 +111,58 @@ export class Engine {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public getAllModels(): SVModel[] {
|
||||||
|
const modelList = Util.convertGroupTable2ModelList(this.modelConstructor.getLayoutGroupTable());
|
||||||
|
const accumulateLeakModels = this.viewContainer.getAccumulateLeakModels();
|
||||||
|
|
||||||
|
return [...modelList, ...accumulateLeakModels];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据配置变化更新视图
|
||||||
|
* @param modelType
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public updateStyle(group: string, newOptions: LayoutGroupOptions) {
|
||||||
|
const models = this.getAllModels(),
|
||||||
|
layoutGroup = this.modelConstructor.getLayoutGroupTable().get(group);
|
||||||
|
|
||||||
|
layoutGroup.options = newOptions;
|
||||||
|
models.forEach(item => {
|
||||||
|
if (item.group !== group) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelType = item.getModelType(),
|
||||||
|
optionsType = layoutGroup.options[modelType];
|
||||||
|
|
||||||
|
if (optionsType) {
|
||||||
|
if (modelType === 'addressLabel') {
|
||||||
|
item.updateG6ModelStyle(item.generateG6ModelProps(optionsType));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const targetModelOption = optionsType[item.sourceType];
|
||||||
|
if (targetModelOption) {
|
||||||
|
item.updateG6ModelStyle(item.generateG6ModelProps(targetModelOption));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用id查找某个节点
|
* 使用id查找某个节点
|
||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
public findElement(id: string) {
|
public findNode(id: string): SVNode {
|
||||||
const elements = this.getNodes();
|
const modelList = this.getAllModels();
|
||||||
const stringId = id.toString();
|
const stringId = id.toString();
|
||||||
const targetElement = elements.find(item => item.sourceId === stringId);
|
const targetNode: SVNode = modelList.find(item => item instanceof SVNode && item.sourceId === stringId) as SVNode;
|
||||||
|
|
||||||
return targetElement;
|
return targetNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -22,10 +22,14 @@ export interface NodeLabelOption {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export interface NodeIndexOption extends NodeLabelOption {
|
export interface AddressLabelOption {
|
||||||
|
offset?: number;
|
||||||
|
style?: Style;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface IndexLabelOption extends NodeLabelOption {
|
||||||
position: 'top' | 'right' | 'bottom' | 'left';
|
position: 'top' | 'right' | 'bottom' | 'left';
|
||||||
value: string;
|
|
||||||
style: Style;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -49,7 +53,6 @@ export interface NodeOption extends ModelOption {
|
|||||||
rotation: number;
|
rotation: number;
|
||||||
label: string | string[];
|
label: string | string[];
|
||||||
anchorPoints: number[][];
|
anchorPoints: number[][];
|
||||||
indexOptions: NodeIndexOption;
|
|
||||||
labelOptions: NodeLabelOption;
|
labelOptions: NodeLabelOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,8 +81,10 @@ export interface LayoutOptions {
|
|||||||
|
|
||||||
export interface LayoutGroupOptions {
|
export interface LayoutGroupOptions {
|
||||||
node: { [key: string]: NodeOption };
|
node: { [key: string]: NodeOption };
|
||||||
link?: { [key: string]: LinkOption }
|
link?: { [key: string]: LinkOption };
|
||||||
marker?: { [key: string]: MarkerOption }
|
marker?: { [key: string]: MarkerOption };
|
||||||
|
addressLabel?: AddressLabelOption;
|
||||||
|
indexLabel?: { [key: string]: IndexLabelOption };
|
||||||
layout?: LayoutOptions;
|
layout?: LayoutOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -118,8 +123,8 @@ export interface EngineOptions {
|
|||||||
|
|
||||||
|
|
||||||
export interface LayoutCreator {
|
export interface LayoutCreator {
|
||||||
defineOptions(): LayoutGroupOptions;
|
defineOptions(sourceData: SourceNode[]): LayoutGroupOptions;
|
||||||
sourcesPreprocess?(sources: SourceNode[], options: LayoutGroupOptions): SourceNode[];
|
sourcesPreprocess?(sourceData: SourceNode[], options: LayoutGroupOptions): SourceNode[];
|
||||||
defineLeakRule?(nodes: SVNode[]): SVNode[];
|
defineLeakRule?(nodes: SVNode[]): SVNode[];
|
||||||
layout(nodes: SVNode[], layoutOptions: LayoutOptions);
|
layout(nodes: SVNode[], layoutOptions: LayoutOptions);
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
|||||||
@ -16,7 +16,10 @@ export interface SourceNode {
|
|||||||
|
|
||||||
|
|
||||||
export type Sources = {
|
export type Sources = {
|
||||||
[key: string]: { data: SourceNode[]; layouter: string; }
|
[key: string]: {
|
||||||
|
data: SourceNode[];
|
||||||
|
layouter: string;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
const path = require('path');
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
mode: 'development',
|
||||||
entry: './src/StructV.ts',
|
entry: './src/StructV.ts',
|
||||||
output: {
|
output: {
|
||||||
filename: './sv.js',
|
filename: './sv.js',
|
||||||
@ -15,7 +16,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
test: /\.ts$/,
|
test: /\.ts$/,
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
loader: 'awesome-typescript-loader'
|
loader: 'ts-loader'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
21
webpack.config.product.js
Normal file
21
webpack.config.product.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: './src/StructV.ts',
|
||||||
|
output: {
|
||||||
|
filename: './sv.js',
|
||||||
|
libraryTarget: 'umd'
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.ts', '.js']
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.ts$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'ts-loader'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
181
yarn.lock
181
yarn.lock
@ -554,20 +554,6 @@ atob@^2.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||||
|
|
||||||
awesome-typescript-loader@^5.2.1:
|
|
||||||
version "5.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz#a41daf7847515f4925cdbaa3075d61f289e913fc"
|
|
||||||
integrity sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==
|
|
||||||
dependencies:
|
|
||||||
chalk "^2.4.1"
|
|
||||||
enhanced-resolve "^4.0.0"
|
|
||||||
loader-utils "^1.1.0"
|
|
||||||
lodash "^4.17.5"
|
|
||||||
micromatch "^3.1.9"
|
|
||||||
mkdirp "^0.5.1"
|
|
||||||
source-map-support "^0.5.3"
|
|
||||||
webpack-log "^1.2.0"
|
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||||
@ -785,20 +771,12 @@ cache-base@^1.0.1:
|
|||||||
union-value "^1.0.0"
|
union-value "^1.0.0"
|
||||||
unset-value "^1.0.0"
|
unset-value "^1.0.0"
|
||||||
|
|
||||||
call-bind@^1.0.0:
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
|
||||||
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
|
|
||||||
dependencies:
|
|
||||||
function-bind "^1.1.1"
|
|
||||||
get-intrinsic "^1.0.2"
|
|
||||||
|
|
||||||
camelcase@^5.0.0:
|
camelcase@^5.0.0:
|
||||||
version "5.3.1"
|
version "5.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||||
|
|
||||||
chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
|
chalk@^2.3.0, chalk@^2.4.2:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||||
@ -1096,14 +1074,6 @@ d3-timer@^1.0.9:
|
|||||||
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5"
|
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5"
|
||||||
integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==
|
integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==
|
||||||
|
|
||||||
d@1, d@^1.0.1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
|
|
||||||
integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
|
|
||||||
dependencies:
|
|
||||||
es5-ext "^0.10.50"
|
|
||||||
type "^1.0.1"
|
|
||||||
|
|
||||||
dagre@^0.8.5:
|
dagre@^0.8.5:
|
||||||
version "0.8.5"
|
version "0.8.5"
|
||||||
resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee"
|
resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee"
|
||||||
@ -1137,13 +1107,6 @@ decode-uri-component@^0.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||||
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
|
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
|
||||||
|
|
||||||
define-properties@^1.1.3:
|
|
||||||
version "1.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
|
||||||
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
|
|
||||||
dependencies:
|
|
||||||
object-keys "^1.0.12"
|
|
||||||
|
|
||||||
define-property@^0.2.5:
|
define-property@^0.2.5:
|
||||||
version "0.2.5"
|
version "0.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
|
resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
|
||||||
@ -1254,32 +1217,6 @@ errno@^0.1.3, errno@~0.1.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prr "~1.0.1"
|
prr "~1.0.1"
|
||||||
|
|
||||||
es5-ext@^0.10.35, es5-ext@^0.10.50:
|
|
||||||
version "0.10.53"
|
|
||||||
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
|
|
||||||
integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
|
|
||||||
dependencies:
|
|
||||||
es6-iterator "~2.0.3"
|
|
||||||
es6-symbol "~3.1.3"
|
|
||||||
next-tick "~1.0.0"
|
|
||||||
|
|
||||||
es6-iterator@~2.0.3:
|
|
||||||
version "2.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
|
|
||||||
integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
|
|
||||||
dependencies:
|
|
||||||
d "1"
|
|
||||||
es5-ext "^0.10.35"
|
|
||||||
es6-symbol "^3.1.1"
|
|
||||||
|
|
||||||
es6-symbol@^3.1.1, es6-symbol@~3.1.3:
|
|
||||||
version "3.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
|
|
||||||
integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
|
|
||||||
dependencies:
|
|
||||||
d "^1.0.1"
|
|
||||||
ext "^1.1.2"
|
|
||||||
|
|
||||||
escape-string-regexp@^1.0.5:
|
escape-string-regexp@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
@ -1348,13 +1285,6 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
homedir-polyfill "^1.0.1"
|
homedir-polyfill "^1.0.1"
|
||||||
|
|
||||||
ext@^1.1.2:
|
|
||||||
version "1.6.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52"
|
|
||||||
integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==
|
|
||||||
dependencies:
|
|
||||||
type "^2.5.0"
|
|
||||||
|
|
||||||
extend-shallow@^2.0.1:
|
extend-shallow@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
|
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
|
||||||
@ -1508,25 +1438,11 @@ fsevents@~2.3.2:
|
|||||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||||
|
|
||||||
function-bind@^1.1.1:
|
|
||||||
version "1.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
|
||||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
|
||||||
|
|
||||||
get-caller-file@^2.0.1:
|
get-caller-file@^2.0.1:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||||
|
|
||||||
get-intrinsic@^1.0.2:
|
|
||||||
version "1.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
|
|
||||||
integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
|
|
||||||
dependencies:
|
|
||||||
function-bind "^1.1.1"
|
|
||||||
has "^1.0.3"
|
|
||||||
has-symbols "^1.0.1"
|
|
||||||
|
|
||||||
get-value@^2.0.3, get-value@^2.0.6:
|
get-value@^2.0.3, get-value@^2.0.6:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
||||||
@ -1627,11 +1543,6 @@ has-flag@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||||
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||||
|
|
||||||
has-symbols@^1.0.1:
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
|
|
||||||
integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
|
|
||||||
|
|
||||||
has-value@^0.3.1:
|
has-value@^0.3.1:
|
||||||
version "0.3.1"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
|
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
|
||||||
@ -1663,13 +1574,6 @@ has-values@^1.0.0:
|
|||||||
is-number "^3.0.0"
|
is-number "^3.0.0"
|
||||||
kind-of "^4.0.0"
|
kind-of "^4.0.0"
|
||||||
|
|
||||||
has@^1.0.3:
|
|
||||||
version "1.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
|
||||||
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
|
||||||
dependencies:
|
|
||||||
function-bind "^1.1.1"
|
|
||||||
|
|
||||||
hash-base@^3.0.0:
|
hash-base@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
|
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
|
||||||
@ -1992,7 +1896,7 @@ loader-runner@^2.4.0:
|
|||||||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
||||||
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
|
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
|
||||||
|
|
||||||
loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
|
loader-utils@^1.0.2, loader-utils@^1.2.3, loader-utils@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
|
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
|
||||||
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
|
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
|
||||||
@ -2009,26 +1913,11 @@ locate-path@^3.0.0:
|
|||||||
p-locate "^3.0.0"
|
p-locate "^3.0.0"
|
||||||
path-exists "^3.0.0"
|
path-exists "^3.0.0"
|
||||||
|
|
||||||
lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.5:
|
lodash@^4.17.15, lodash@^4.17.19:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
|
||||||
log-symbols@^2.1.0:
|
|
||||||
version "2.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
|
|
||||||
integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
|
|
||||||
dependencies:
|
|
||||||
chalk "^2.0.1"
|
|
||||||
|
|
||||||
loglevelnext@^1.0.1:
|
|
||||||
version "1.0.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2"
|
|
||||||
integrity sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==
|
|
||||||
dependencies:
|
|
||||||
es6-symbol "^3.1.1"
|
|
||||||
object.assign "^4.1.0"
|
|
||||||
|
|
||||||
lru-cache@^5.1.1:
|
lru-cache@^5.1.1:
|
||||||
version "5.1.1"
|
version "5.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
|
||||||
@ -2081,7 +1970,7 @@ memory-fs@^0.5.0:
|
|||||||
errno "^0.1.3"
|
errno "^0.1.3"
|
||||||
readable-stream "^2.0.1"
|
readable-stream "^2.0.1"
|
||||||
|
|
||||||
micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.9:
|
micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
|
||||||
version "3.1.10"
|
version "3.1.10"
|
||||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
|
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
|
||||||
integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
|
integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
|
||||||
@ -2235,11 +2124,6 @@ neo-async@^2.5.0, neo-async@^2.6.1:
|
|||||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||||
|
|
||||||
next-tick@~1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
|
|
||||||
integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
|
|
||||||
|
|
||||||
nice-try@^1.0.4:
|
nice-try@^1.0.4:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||||
@ -2300,11 +2184,6 @@ object-copy@^0.1.0:
|
|||||||
define-property "^0.2.5"
|
define-property "^0.2.5"
|
||||||
kind-of "^3.0.3"
|
kind-of "^3.0.3"
|
||||||
|
|
||||||
object-keys@^1.0.12, object-keys@^1.1.1:
|
|
||||||
version "1.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
|
||||||
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
|
||||||
|
|
||||||
object-visit@^1.0.0:
|
object-visit@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
|
resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
|
||||||
@ -2312,16 +2191,6 @@ object-visit@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isobject "^3.0.0"
|
isobject "^3.0.0"
|
||||||
|
|
||||||
object.assign@^4.1.0:
|
|
||||||
version "4.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
|
|
||||||
integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
|
|
||||||
dependencies:
|
|
||||||
call-bind "^1.0.0"
|
|
||||||
define-properties "^1.1.3"
|
|
||||||
has-symbols "^1.0.1"
|
|
||||||
object-keys "^1.1.1"
|
|
||||||
|
|
||||||
object.pick@^1.3.0:
|
object.pick@^1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
|
resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
|
||||||
@ -2741,7 +2610,7 @@ schema-utils@^1.0.0:
|
|||||||
ajv-errors "^1.0.0"
|
ajv-errors "^1.0.0"
|
||||||
ajv-keywords "^3.1.0"
|
ajv-keywords "^3.1.0"
|
||||||
|
|
||||||
semver@^5.5.0, semver@^5.6.0:
|
semver@^5.0.1, semver@^5.5.0, semver@^5.6.0:
|
||||||
version "5.7.1"
|
version "5.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||||
@ -2846,7 +2715,7 @@ source-map-resolve@^0.5.0:
|
|||||||
source-map-url "^0.4.0"
|
source-map-url "^0.4.0"
|
||||||
urix "^0.1.0"
|
urix "^0.1.0"
|
||||||
|
|
||||||
source-map-support@^0.5.3, source-map-support@~0.5.12:
|
source-map-support@~0.5.12:
|
||||||
version "0.5.20"
|
version "0.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
|
||||||
integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
|
integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
|
||||||
@ -3053,6 +2922,17 @@ to-regex@^3.0.1, to-regex@^3.0.2:
|
|||||||
regex-not "^1.0.2"
|
regex-not "^1.0.2"
|
||||||
safe-regex "^1.1.0"
|
safe-regex "^1.1.0"
|
||||||
|
|
||||||
|
ts-loader@^5.2.1:
|
||||||
|
version "5.4.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.4.5.tgz#a0c1f034b017a9344cef0961bfd97cc192492b8b"
|
||||||
|
integrity sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==
|
||||||
|
dependencies:
|
||||||
|
chalk "^2.3.0"
|
||||||
|
enhanced-resolve "^4.0.0"
|
||||||
|
loader-utils "^1.0.2"
|
||||||
|
micromatch "^3.1.4"
|
||||||
|
semver "^5.0.1"
|
||||||
|
|
||||||
tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0:
|
tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0:
|
||||||
version "2.3.1"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
||||||
@ -3063,16 +2943,6 @@ tty-browserify@0.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
|
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
|
||||||
integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
|
integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
|
||||||
|
|
||||||
type@^1.0.1:
|
|
||||||
version "1.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
|
|
||||||
integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
|
|
||||||
|
|
||||||
type@^2.5.0:
|
|
||||||
version "2.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d"
|
|
||||||
integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==
|
|
||||||
|
|
||||||
typedarray@^0.0.6:
|
typedarray@^0.0.6:
|
||||||
version "0.0.6"
|
version "0.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||||
@ -3164,11 +3034,6 @@ util@^0.11.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
inherits "2.0.3"
|
inherits "2.0.3"
|
||||||
|
|
||||||
uuid@^3.1.0:
|
|
||||||
version "3.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
|
||||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
|
||||||
|
|
||||||
v8-compile-cache@^2.1.1:
|
v8-compile-cache@^2.1.1:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||||
@ -3214,16 +3079,6 @@ webpack-cli@^3.2.3:
|
|||||||
v8-compile-cache "^2.1.1"
|
v8-compile-cache "^2.1.1"
|
||||||
yargs "^13.3.2"
|
yargs "^13.3.2"
|
||||||
|
|
||||||
webpack-log@^1.2.0:
|
|
||||||
version "1.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d"
|
|
||||||
integrity sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==
|
|
||||||
dependencies:
|
|
||||||
chalk "^2.1.0"
|
|
||||||
log-symbols "^2.1.0"
|
|
||||||
loglevelnext "^1.0.1"
|
|
||||||
uuid "^3.1.0"
|
|
||||||
|
|
||||||
webpack-sources@^1.4.0, webpack-sources@^1.4.1:
|
webpack-sources@^1.4.0, webpack-sources@^1.4.1:
|
||||||
version "1.4.3"
|
version "1.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
|
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
|
||||||
@ -3232,7 +3087,7 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1:
|
|||||||
source-list-map "^2.0.0"
|
source-list-map "^2.0.0"
|
||||||
source-map "~0.6.1"
|
source-map "~0.6.1"
|
||||||
|
|
||||||
webpack@^4.28.2:
|
webpack@^4.46.0:
|
||||||
version "4.46.0"
|
version "4.46.0"
|
||||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542"
|
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542"
|
||||||
integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==
|
integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user