feat: 添加可以focus节点的函数
This commit is contained in:
parent
3160813119
commit
8347476980
@ -7,7 +7,7 @@ SV.registerLayouter('BinaryTree', {
|
||||
default: {
|
||||
type: 'binary-tree-node',
|
||||
size: [60, 30],
|
||||
label: '[id]',
|
||||
label: '[data]',
|
||||
style: {
|
||||
fill: '#b83b5e',
|
||||
stroke: "#333",
|
||||
|
@ -18,7 +18,7 @@ SV.registerLayouter('LinkList', {
|
||||
element: {
|
||||
default: {
|
||||
type: 'link-list-node',
|
||||
label: '[id]',
|
||||
label: '[data]',
|
||||
size: [60, 30],
|
||||
style: {
|
||||
stroke: '#333',
|
||||
|
@ -79,6 +79,7 @@
|
||||
<script src="./Layouter/AdjoinTableGraph.js"></script>
|
||||
<script>
|
||||
|
||||
const curSelectData = { element: null, style: null };
|
||||
|
||||
let cur = SV(document.getElementById('container'), {
|
||||
freedContainer: document.getElementById('freed'),
|
||||
@ -90,39 +91,58 @@
|
||||
|
||||
|
||||
let data = [{
|
||||
GeneralizedList: {
|
||||
data: [
|
||||
"LinkList0": {
|
||||
"data": [
|
||||
{
|
||||
"type": "table",
|
||||
"id": 1000,
|
||||
"next": "table#1001",
|
||||
"tag": 1,
|
||||
"sub": "atom#1002",
|
||||
root: true,
|
||||
"external": [
|
||||
"gl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "table",
|
||||
"id": 1001,
|
||||
"tag": 1,
|
||||
"external": [
|
||||
"gl1"
|
||||
"id": "0x617fb0",
|
||||
"data": "N",
|
||||
"next": "0x617ff0",
|
||||
"rootExternal": [
|
||||
"before"
|
||||
],
|
||||
loopNext: 'table#1000'
|
||||
"type": "default"
|
||||
},
|
||||
{
|
||||
"type": "atom",
|
||||
"id": 1002,
|
||||
"tag": 0,
|
||||
"data": "e",
|
||||
"external": [
|
||||
"p4"
|
||||
]
|
||||
"id": "0x617ff0",
|
||||
"data": "A",
|
||||
"next": "0x618010",
|
||||
"type": "default"
|
||||
},
|
||||
{
|
||||
"id": "0x618010",
|
||||
"data": "A",
|
||||
"next": "0x618030",
|
||||
"type": "default"
|
||||
},
|
||||
{
|
||||
"id": "0x618030",
|
||||
"data": "B",
|
||||
"next": "0x618050",
|
||||
"type": "default"
|
||||
},
|
||||
{
|
||||
"id": "0x618050",
|
||||
"data": "N",
|
||||
"next": null,
|
||||
"type": "default"
|
||||
}
|
||||
],
|
||||
layouter: "GeneralizedList"
|
||||
"layouter": "LinkList"
|
||||
},
|
||||
"LinkList1": {
|
||||
"data": [
|
||||
{
|
||||
"freed": true,
|
||||
"id": "0x617fd0",
|
||||
"data": "",
|
||||
"next": "0x605010",
|
||||
"rootExternal": [
|
||||
"tmpNode"
|
||||
],
|
||||
"type": "default"
|
||||
}
|
||||
],
|
||||
"layouter": "LinkList"
|
||||
}
|
||||
}];
|
||||
|
||||
@ -142,10 +162,12 @@
|
||||
document.getElementById('btn-next').addEventListener('click', e => {
|
||||
curData = data[++dataIndex];
|
||||
cur.render(curData);
|
||||
// curSelectData.element = null;
|
||||
// curSelectData.style = null;
|
||||
});
|
||||
|
||||
document.getElementById('btn-prev').addEventListener('click', e => {
|
||||
curData = data[--dataIndex]
|
||||
curData = data[--dataIndex];
|
||||
cur.render(curData);
|
||||
});
|
||||
|
||||
@ -164,6 +186,41 @@
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 选中一个element
|
||||
*/
|
||||
function selectElement(element) {
|
||||
if (element === curSelectData.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (curSelectData.element) {
|
||||
const style = curSelectData.style;
|
||||
curSelectData.element.set("style", style);
|
||||
}
|
||||
|
||||
curSelectData.element = element;
|
||||
curSelectData.style = { ...element.get("style") };
|
||||
this.setSelectElementStyle(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置选中的节点的颜色
|
||||
*/
|
||||
function setSelectElementStyle(element) {
|
||||
element.set("style", {
|
||||
fill: "#e23e57",
|
||||
});
|
||||
}
|
||||
|
||||
cur.on('node:click', ele => {
|
||||
selectElement(ele);
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
2
dist/sv.js
vendored
2
dist/sv.js
vendored
File diff suppressed because one or more lines are too long
@ -44,6 +44,8 @@ export class Model {
|
||||
id: string;
|
||||
type: string;
|
||||
isLeak: boolean;
|
||||
isDestroy: boolean;
|
||||
modelType: string;
|
||||
|
||||
props: G6NodeModel | G6EdgeModel;
|
||||
shadowG6Item;
|
||||
@ -58,6 +60,7 @@ export class Model {
|
||||
this.G6Item = null;
|
||||
this.props = <G6NodeModel | G6EdgeModel>{ };
|
||||
this.isLeak = false;
|
||||
this.isDestroy = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,6 +103,10 @@ export class Model {
|
||||
* @returns
|
||||
*/
|
||||
set(attr: string | object, value?: any) {
|
||||
if(this.isDestroy) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof attr === 'object') {
|
||||
Object.keys(attr).map(item => {
|
||||
this.set(item, attr[item]);
|
||||
@ -158,6 +165,10 @@ export class Model {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
getModelType(): string {
|
||||
return this.modelType;
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return this.id;
|
||||
}
|
||||
@ -178,6 +189,7 @@ export class Element extends Model {
|
||||
|
||||
constructor(id: string, type: string, group: string, layouter: string, sourceElement: SourceElement) {
|
||||
super(id, type);
|
||||
this.modelType = 'element';
|
||||
|
||||
if(type === null) {
|
||||
return;
|
||||
@ -219,6 +231,10 @@ export class Element extends Model {
|
||||
SVModelName: this.type
|
||||
};
|
||||
}
|
||||
|
||||
getSourceId(): string {
|
||||
return this.sourceId;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -230,6 +246,8 @@ export class Link extends Model {
|
||||
|
||||
constructor(id: string, type: string, element: Element, target: Element, index: number) {
|
||||
super(id, type);
|
||||
this.modelType = 'link';
|
||||
|
||||
this.element = element;
|
||||
this.target = target;
|
||||
this.index = index;
|
||||
@ -277,6 +295,8 @@ export class Marker extends Model {
|
||||
|
||||
constructor(id: string, type: string, label: string | string[], target: Element) {
|
||||
super(id, type);
|
||||
this.modelType = 'marker';
|
||||
|
||||
this.target = target;
|
||||
this.label = label;
|
||||
|
||||
|
@ -106,13 +106,15 @@ import { Container } from "./container";
|
||||
protected afterInitRenderer() {
|
||||
let g6Instance = this.getG6Instance(),
|
||||
marker = null,
|
||||
markerX = null,
|
||||
markerY = null,
|
||||
dragStartX = null,
|
||||
dragStartY = null;
|
||||
markerX = 0,
|
||||
markerY = 0,
|
||||
dragStartX = 0,
|
||||
dragStartY = 0,
|
||||
element = null;
|
||||
|
||||
g6Instance.on('node:dragstart', ev => {
|
||||
const model = ev.item.getModel();
|
||||
element = ev.item.SVModel;
|
||||
|
||||
if(model.SVModelType === 'marker') {
|
||||
return;
|
||||
@ -128,22 +130,33 @@ import { Container } from "./container";
|
||||
return;
|
||||
}
|
||||
|
||||
dragStartX = ev.canvasX;
|
||||
dragStartY = ev.canvasY;
|
||||
marker = g6Instance.findById(model.markerId);
|
||||
|
||||
if(marker) {
|
||||
markerX = marker.getModel().x,
|
||||
markerY = marker.getModel().y;
|
||||
dragStartX = ev.canvasX;
|
||||
dragStartY = ev.canvasY;
|
||||
}
|
||||
});
|
||||
|
||||
g6Instance.on('node:dragend', ev => {
|
||||
let distanceX = ev.canvasX - dragStartX,
|
||||
distanceY = ev.canvasY - dragStartY,
|
||||
elementX = element.get('x'),
|
||||
elementY = element.get('y');
|
||||
|
||||
element.set({
|
||||
x: elementX + distanceX,
|
||||
y: elementY + distanceY
|
||||
});
|
||||
|
||||
marker = null;
|
||||
markerX = null,
|
||||
markerY = null,
|
||||
dragStartX = null,
|
||||
dragStartY = null;
|
||||
markerX = 0,
|
||||
markerY = 0,
|
||||
dragStartX = 0,
|
||||
dragStartY = 0;
|
||||
element = null;
|
||||
});
|
||||
|
||||
g6Instance.on('node:drag', ev => {
|
||||
|
@ -21,6 +21,7 @@ export class Renderer {
|
||||
private DOMContainer: HTMLElement; // 主可视化视图容器
|
||||
private g6Instance; // g6 实例
|
||||
|
||||
private prevRenderModelList: Model[] = null;
|
||||
private isFirstRender: boolean; // 是否为第一次渲染
|
||||
|
||||
constructor(engine: Engine, DOMContainer: HTMLElement, g6Options: { [key: string]: any }) {
|
||||
@ -72,12 +73,8 @@ export class Renderer {
|
||||
* @param modelList
|
||||
*/
|
||||
public render(modelList: Model[], removeModels: Model[]) {
|
||||
let data: G6Data = Util.convertModelList2G6Data(modelList),
|
||||
removeData: G6Data = Util.convertModelList2G6Data(removeModels),
|
||||
renderData: G6Data = {
|
||||
nodes: [...data.nodes, ...removeData.nodes],
|
||||
edges: [...data.edges, ...removeData.edges]
|
||||
};
|
||||
const renderModelList = [...modelList, ...removeModels],
|
||||
renderData: G6Data = Util.convertModelList2G6Data(renderModelList);
|
||||
|
||||
if(this.isFirstRender) {
|
||||
this.g6Instance.read(renderData);
|
||||
@ -99,6 +96,13 @@ export class Renderer {
|
||||
}
|
||||
});
|
||||
|
||||
// 将上一次的model全部标记为已销毁
|
||||
if(this.prevRenderModelList) {
|
||||
this.prevRenderModelList.forEach(item => { item.isDestroy = true; });
|
||||
}
|
||||
|
||||
this.prevRenderModelList = renderModelList;
|
||||
|
||||
// 把所有连线置顶
|
||||
if(this.isFirstRender) {
|
||||
this.g6Instance.getEdges().forEach(item => item.toFront());
|
||||
|
@ -124,7 +124,15 @@ export class ViewManager {
|
||||
this.handleFreedLabel(freedElements, prevLayoutGroupTable.get(freedGroupName));
|
||||
this.prevFreedElements = freedElements;
|
||||
|
||||
return [...freedElements, ...freedMarkers];
|
||||
const freedItems = [...freedElements, ...freedMarkers];
|
||||
freedItems.forEach(item => {
|
||||
item.set('style', {
|
||||
fill: '#ccc'
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
return freedItems;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -200,18 +200,15 @@ export class Engine {
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用id选中某个节点
|
||||
* 使用id查找某个节点
|
||||
* @param id
|
||||
* @param callback
|
||||
*/
|
||||
public selectElement(id: string, callback?: (element: Element) => void) {
|
||||
public findElement(id: string) {
|
||||
const elements = this.getElements();
|
||||
const stringId = id.toString();
|
||||
const targetElement = elements.find(item => item.sourceId === stringId);
|
||||
|
||||
if(targetElement) {
|
||||
callback && callback(targetElement);
|
||||
}
|
||||
return targetElement;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -239,7 +236,9 @@ export class Engine {
|
||||
return;
|
||||
}
|
||||
|
||||
this.viewManager.getG6Instance().on(eventName, callback);
|
||||
this.viewManager.getG6Instance().on(eventName, event => {
|
||||
callback(event.item.SVModel);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user