feat: 添加可以focus节点的函数

This commit is contained in:
黎智洲 2021-09-13 21:35:59 +08:00
parent 3160813119
commit 8347476980
9 changed files with 156 additions and 55 deletions

View File

@ -7,7 +7,7 @@ SV.registerLayouter('BinaryTree', {
default: {
type: 'binary-tree-node',
size: [60, 30],
label: '[id]',
label: '[data]',
style: {
fill: '#b83b5e',
stroke: "#333",

View File

@ -18,7 +18,7 @@ SV.registerLayouter('LinkList', {
element: {
default: {
type: 'link-list-node',
label: '[id]',
label: '[data]',
size: [60, 30],
style: {
stroke: '#333',

View File

@ -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

File diff suppressed because one or more lines are too long

View File

@ -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;

View File

@ -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 => {

View File

@ -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());

View File

@ -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;
}
/**

View File

@ -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);
});
}
/**