fix: 大量bug修复
This commit is contained in:
parent
0291c74523
commit
f6ab581815
@ -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);
|
||||||
@ -66,3 +66,67 @@ SV.registerLayout('Array', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SV.registerLayout('Array', {
|
||||||
|
|
||||||
|
sourcesPreprocess(sources) {
|
||||||
|
const firstElement = sources[0];
|
||||||
|
|
||||||
|
if(firstElement.external) {
|
||||||
|
firstElement.headExternal = firstElement.external;
|
||||||
|
delete firstElement.external;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sources;
|
||||||
|
},
|
||||||
|
|
||||||
|
defineOptions() {
|
||||||
|
return {
|
||||||
|
element: {
|
||||||
|
default: {
|
||||||
|
type: 'indexed-node',
|
||||||
|
label: '[id]',
|
||||||
|
size: [60, 30],
|
||||||
|
style: {
|
||||||
|
stroke: '#333',
|
||||||
|
fill: '#355c7d'
|
||||||
|
},
|
||||||
|
indexOptions: {
|
||||||
|
index: { position: 'bottom' },
|
||||||
|
indexTop: { position: 'top' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
marker: {
|
||||||
|
headExternal: {
|
||||||
|
type: 'pointer',
|
||||||
|
anchor: 3,
|
||||||
|
style: {
|
||||||
|
fill: '#f08a5d'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
external: {
|
||||||
|
type: 'pointer',
|
||||||
|
anchor: 0,
|
||||||
|
style: {
|
||||||
|
fill: '#f08a5d'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
layout(elements) {
|
||||||
|
let arr = elements;
|
||||||
|
|
||||||
|
for(let i = 0; i < arr.length; i++) {
|
||||||
|
let width = arr[i].get('size')[0];
|
||||||
|
|
||||||
|
if(i > 0) {
|
||||||
|
arr[i].set('x', arr[i - 1].get('x') + width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 'colorful');
|
||||||
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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -61,6 +61,7 @@
|
|||||||
<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="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>
|
||||||
@ -83,6 +84,7 @@
|
|||||||
<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>
|
<script>
|
||||||
|
|
||||||
const curSelectData = { element: null, style: null };
|
const curSelectData = { element: null, style: null };
|
||||||
@ -96,42 +98,31 @@
|
|||||||
|
|
||||||
|
|
||||||
let data = [{
|
let data = [{
|
||||||
"LinkList0": {
|
Array: {
|
||||||
"data": [
|
data: [{ id: 1, data: 1 }, { id: 2, data: 2 }, { id: 3, data: 3 }, { id: 4, data: 4 }],
|
||||||
{ id: 0, data: 'A', index: 1 },
|
layouter: 'Array'
|
||||||
{ id: 1, data: 'B', index: 2 },
|
|
||||||
{ id: 2, data: 'C' }
|
|
||||||
],
|
|
||||||
"layouter": "Array"
|
|
||||||
},
|
|
||||||
"LinkList1": {
|
|
||||||
"data": [
|
|
||||||
{ id: 10, data: 'A', next: 11 },
|
|
||||||
{ id: 11, data: 'B', next: 12 },
|
|
||||||
{ id: 12, data: 'C', next: 13 },
|
|
||||||
{ id: 13, data: 'D' }
|
|
||||||
],
|
|
||||||
"layouter": "LinkList"
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"LinkList0": {
|
Array: {
|
||||||
"data": [
|
data: [{ id: 1, data: 1 }, { id: 2, data: 2 }, { id: 3, data: 3 }],
|
||||||
{ id: 10, data: 'A', next: 11, external: 'true' },
|
layouter: 'Array'
|
||||||
{ id: 11, next: 12, freed: true }
|
|
||||||
],
|
|
||||||
"layouter": "LinkList"
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"LinkList0": {
|
Array: {
|
||||||
"data": [
|
data: [{ id: 1, data: 1 }, { id: 2, data: 2 }],
|
||||||
{ id: 0, data: 'A' }
|
layouter: 'Array'
|
||||||
],
|
}
|
||||||
"layouter": "LinkList"
|
}, {
|
||||||
|
Array: {
|
||||||
|
data: [{ id: 1, data: 1 }, { id: 5, data: 5 }],
|
||||||
|
layouter: 'Array'
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let dataIndex = 0,
|
let dataIndex = 0,
|
||||||
curData = data[dataIndex];
|
curData = data[dataIndex];
|
||||||
|
|
||||||
@ -156,15 +147,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 => {
|
document.getElementById('relayout').addEventListener('click', e => {
|
||||||
console.log();
|
|
||||||
cur.reLayout();
|
cur.reLayout();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById('switch-mode').addEventListener('click', e => {
|
||||||
|
cur.switchMode('Array', 'colorful');
|
||||||
|
});
|
||||||
|
|
||||||
const leak = document.getElementById('leak');
|
const leak = document.getElementById('leak');
|
||||||
|
|
||||||
cur.on('onLeakAreaUpdate', payload => {
|
cur.on('onLeakAreaUpdate', payload => {
|
||||||
|
|||||||
2396
dist/sv.js
vendored
2396
dist/sv.js
vendored
File diff suppressed because one or more lines are too long
12
package.json
12
package.json
@ -3,13 +3,15 @@
|
|||||||
"@antv/g6": "^4.4.1"
|
"@antv/g6": "^4.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"webpack": "^4.46.0",
|
|
||||||
"webpack-cli": "^3.2.3",
|
|
||||||
"ts-loader": "^5.2.1",
|
"ts-loader": "^5.2.1",
|
||||||
"typescript": "^3.2.2"
|
"typescript": "^3.2.2",
|
||||||
|
"webpack": "^4.46.0",
|
||||||
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -102,7 +102,8 @@ export class SVModel {
|
|||||||
// 更新G6Item
|
// 更新G6Item
|
||||||
if (this.G6Item) {
|
if (this.G6Item) {
|
||||||
if (this.preLayout) {
|
if (this.preLayout) {
|
||||||
this.G6Item.getModel()[attr] = value;
|
const G6ItemModel = this.G6Item.getModel();
|
||||||
|
G6ItemModel[attr] = value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.g6Instance.updateItem(this.G6Item, this.G6ModelProps);
|
this.g6Instance.updateItem(this.G6Item, this.G6ModelProps);
|
||||||
|
|||||||
@ -116,7 +116,7 @@ export class SVNode extends SVModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected generateG6ModelProps(options: NodeOption): NodeConfig {
|
protected generateG6ModelProps(options: NodeOption): NodeConfig {
|
||||||
let indexOptions = Util.objectClone<NodeIndexOption>(options.indexOptions);
|
let indexOptions = Util.objectClone<NodeIndexOption>(options.indexOptions) || { index: { position: 'bottom' } };
|
||||||
|
|
||||||
if (indexOptions) {
|
if (indexOptions) {
|
||||||
Object.keys(indexOptions).map(key => {
|
Object.keys(indexOptions).map(key => {
|
||||||
|
|||||||
@ -43,13 +43,13 @@ export class ModelConstructor {
|
|||||||
*/
|
*/
|
||||||
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]: { [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],
|
||||||
layout = sourceGroup.layouter,
|
layout = sourceGroup.layouter,
|
||||||
layoutCreator: LayoutCreator = layoutMap[layout];
|
mode = sourceGroup.mode || 'default',
|
||||||
|
layoutCreator: LayoutCreator = layoutMap[layout][mode];
|
||||||
|
|
||||||
if (!layout || !layoutCreator) {
|
if (!layout || !layoutCreator) {
|
||||||
return;
|
return;
|
||||||
@ -66,7 +66,7 @@ export class ModelConstructor {
|
|||||||
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 || {};
|
||||||
@ -396,5 +396,6 @@ export class ModelConstructor {
|
|||||||
*/
|
*/
|
||||||
destroy() {
|
destroy() {
|
||||||
this.layoutGroupTable = null;
|
this.layoutGroupTable = null;
|
||||||
|
this.prevSourcesStringMap = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -26,7 +26,7 @@ export interface StructV {
|
|||||||
|
|
||||||
registeredShape: any[];
|
registeredShape: any[];
|
||||||
|
|
||||||
registeredLayout: { [key: string]: LayoutCreator },
|
registeredLayout: { [key: string]: { [key: string]: LayoutCreator } },
|
||||||
|
|
||||||
registerShape: Function,
|
registerShape: Function,
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ SV.registeredShape = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
SV.registerShape = G6.registerNode;
|
SV.registerShape = G6.registerNode;
|
||||||
SV.registerLayout = function(name: string, layoutCreator: LayoutCreator) {
|
SV.registerLayout = function(name: string, layoutCreator: LayoutCreator, mode: string = 'default') {
|
||||||
|
|
||||||
if(typeof layoutCreator.sourcesPreprocess !== 'function') {
|
if(typeof layoutCreator.sourcesPreprocess !== 'function') {
|
||||||
layoutCreator.sourcesPreprocess = function(data: SourceNode[]): SourceNode[] {
|
layoutCreator.sourcesPreprocess = function(data: SourceNode[]): SourceNode[] {
|
||||||
@ -79,7 +79,11 @@ SV.registerLayout = function(name: string, layoutCreator: LayoutCreator) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SV.registeredLayout[name] = layoutCreator;
|
if(SV.registeredLayout[name] === undefined) {
|
||||||
|
SV.registeredLayout[name] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
SV.registeredLayout[name][mode] = layoutCreator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -265,6 +265,7 @@ export class LayoutProvider {
|
|||||||
* @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);
|
this.preLayoutProcess(layoutGroupTable);
|
||||||
|
|||||||
@ -25,11 +25,13 @@ export class Reconcile {
|
|||||||
|
|
||||||
private engine: Engine;
|
private engine: Engine;
|
||||||
private renderer: Renderer;
|
private renderer: Renderer;
|
||||||
|
private prevChangeModels: SVModel[];
|
||||||
private isFirstPatch: boolean;
|
private isFirstPatch: boolean;
|
||||||
|
|
||||||
constructor(engine: Engine, renderer: Renderer) {
|
constructor(engine: Engine, renderer: Renderer) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
|
this.prevChangeModels = [];
|
||||||
this.isFirstPatch = true;
|
this.isFirstPatch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,6 +318,10 @@ export class Reconcile {
|
|||||||
* @param models
|
* @param models
|
||||||
*/
|
*/
|
||||||
private handleChangeModels(models: SVModel[]) {
|
private handleChangeModels(models: SVModel[]) {
|
||||||
|
if(models.length === 0) {
|
||||||
|
models = this.prevChangeModels;
|
||||||
|
}
|
||||||
|
|
||||||
const changeHighlightColor: string = this.engine.viewOptions.updateHighlight;
|
const changeHighlightColor: string = this.engine.viewOptions.updateHighlight;
|
||||||
|
|
||||||
if (!changeHighlightColor || typeof changeHighlightColor !== 'string') {
|
if (!changeHighlightColor || typeof changeHighlightColor !== 'string') {
|
||||||
@ -338,6 +344,8 @@ export class Reconcile {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.prevChangeModels = models;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -389,6 +397,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);
|
||||||
@ -399,10 +409,13 @@ 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() {
|
||||||
|
this.prevChangeModels.length = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -115,6 +115,9 @@ export class Renderer {
|
|||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -61,8 +61,19 @@ export class ViewContainer {
|
|||||||
* 对主视图进行重新布局
|
* 对主视图进行重新布局
|
||||||
*/
|
*/
|
||||||
reLayout() {
|
reLayout() {
|
||||||
this.layoutProvider.layoutAll(this.prevLayoutGroupTable, [], this.accumulateLeakModels);
|
const g6Instance = this.getG6Instance(),
|
||||||
this.getG6Instance().refresh();
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -156,6 +167,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -163,15 +179,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;
|
||||||
@ -180,11 +190,9 @@ export class ViewContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 把渲染后要触发的逻辑放在这里
|
* 把渲染前要触发的逻辑放在这里
|
||||||
*/
|
*/
|
||||||
private beforeRender() {
|
private beforeRender() { }
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
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, ViewOptions } from "./options";
|
||||||
import { SV } from "./StructV";
|
import { SV } from "./StructV";
|
||||||
import { EventBus } from "./Common/eventBus";
|
import { EventBus } from "./Common/eventBus";
|
||||||
import { ViewContainer } from "./View/viewContainer";
|
import { ViewContainer } from "./View/viewContainer";
|
||||||
@ -11,18 +11,16 @@ import { SVMarker } from "./Model/SVMarker";
|
|||||||
|
|
||||||
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({
|
||||||
@ -46,40 +44,55 @@ 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
|
||||||
*/
|
*/
|
||||||
public render(sourceData: Sources) {
|
public render(source: Sources) {
|
||||||
if(sourceData === undefined || sourceData === null) {
|
if(source === undefined || source === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
``
|
||||||
|
let stringSource = JSON.stringify(source);
|
||||||
|
if(this.prevStringSource === stringSource) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let stringSourceData = JSON.stringify(sourceData);
|
this.prevSource = source;
|
||||||
if(this.prevStringSourceData === stringSourceData) {
|
this.prevStringSource = stringSource;
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换指定数据结构的 mode 主题
|
||||||
|
* @param mode
|
||||||
|
*/
|
||||||
|
public switchMode(layout: string, mode: string) {
|
||||||
|
if(this.prevSource === undefined || this.prevSource === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(this.prevSource).map(group => {
|
||||||
|
let sourceGroup = this.prevSource[group];
|
||||||
|
|
||||||
|
if(sourceGroup.layouter === layout) {
|
||||||
|
sourceGroup.mode = mode;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.render(this.prevSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重新布局
|
* 重新布局
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -118,8 +118,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,11 @@ export interface SourceNode {
|
|||||||
|
|
||||||
|
|
||||||
export type Sources = {
|
export type Sources = {
|
||||||
[key: string]: { data: SourceNode[]; layouter: string; }
|
[key: string]: {
|
||||||
|
data: SourceNode[];
|
||||||
|
layouter: string;
|
||||||
|
mode?: string
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const path = require('path');
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@ -20,5 +20,5 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
// devtool: 'eval-source-map'
|
devtool: 'eval-source-map'
|
||||||
};
|
};
|
||||||
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'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user