feat: 添加可以focus节点的函数
This commit is contained in:
parent
3160813119
commit
8347476980
@ -7,7 +7,7 @@ SV.registerLayouter('BinaryTree', {
|
|||||||
default: {
|
default: {
|
||||||
type: 'binary-tree-node',
|
type: 'binary-tree-node',
|
||||||
size: [60, 30],
|
size: [60, 30],
|
||||||
label: '[id]',
|
label: '[data]',
|
||||||
style: {
|
style: {
|
||||||
fill: '#b83b5e',
|
fill: '#b83b5e',
|
||||||
stroke: "#333",
|
stroke: "#333",
|
||||||
|
@ -18,7 +18,7 @@ SV.registerLayouter('LinkList', {
|
|||||||
element: {
|
element: {
|
||||||
default: {
|
default: {
|
||||||
type: 'link-list-node',
|
type: 'link-list-node',
|
||||||
label: '[id]',
|
label: '[data]',
|
||||||
size: [60, 30],
|
size: [60, 30],
|
||||||
style: {
|
style: {
|
||||||
stroke: '#333',
|
stroke: '#333',
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
<script src="./Layouter/AdjoinTableGraph.js"></script>
|
<script src="./Layouter/AdjoinTableGraph.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
const curSelectData = { element: null, style: null };
|
||||||
|
|
||||||
let cur = SV(document.getElementById('container'), {
|
let cur = SV(document.getElementById('container'), {
|
||||||
freedContainer: document.getElementById('freed'),
|
freedContainer: document.getElementById('freed'),
|
||||||
@ -90,39 +91,58 @@
|
|||||||
|
|
||||||
|
|
||||||
let data = [{
|
let data = [{
|
||||||
GeneralizedList: {
|
"LinkList0": {
|
||||||
data: [
|
"data": [
|
||||||
{
|
{
|
||||||
"type": "table",
|
"id": "0x617fb0",
|
||||||
"id": 1000,
|
"data": "N",
|
||||||
"next": "table#1001",
|
"next": "0x617ff0",
|
||||||
"tag": 1,
|
"rootExternal": [
|
||||||
"sub": "atom#1002",
|
"before"
|
||||||
root: true,
|
|
||||||
"external": [
|
|
||||||
"gl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "table",
|
|
||||||
"id": 1001,
|
|
||||||
"tag": 1,
|
|
||||||
"external": [
|
|
||||||
"gl1"
|
|
||||||
],
|
],
|
||||||
loopNext: 'table#1000'
|
"type": "default"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "atom",
|
"id": "0x617ff0",
|
||||||
"id": 1002,
|
"data": "A",
|
||||||
"tag": 0,
|
"next": "0x618010",
|
||||||
"data": "e",
|
"type": "default"
|
||||||
"external": [
|
|
||||||
"p4"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"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 => {
|
document.getElementById('btn-next').addEventListener('click', e => {
|
||||||
curData = data[++dataIndex];
|
curData = data[++dataIndex];
|
||||||
cur.render(curData);
|
cur.render(curData);
|
||||||
|
// curSelectData.element = null;
|
||||||
|
// curSelectData.style = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('btn-prev').addEventListener('click', e => {
|
document.getElementById('btn-prev').addEventListener('click', e => {
|
||||||
curData = data[--dataIndex]
|
curData = data[--dataIndex];
|
||||||
cur.render(curData);
|
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>
|
</script>
|
||||||
</body>
|
</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;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
isLeak: boolean;
|
isLeak: boolean;
|
||||||
|
isDestroy: boolean;
|
||||||
|
modelType: string;
|
||||||
|
|
||||||
props: G6NodeModel | G6EdgeModel;
|
props: G6NodeModel | G6EdgeModel;
|
||||||
shadowG6Item;
|
shadowG6Item;
|
||||||
@ -58,6 +60,7 @@ export class Model {
|
|||||||
this.G6Item = null;
|
this.G6Item = null;
|
||||||
this.props = <G6NodeModel | G6EdgeModel>{ };
|
this.props = <G6NodeModel | G6EdgeModel>{ };
|
||||||
this.isLeak = false;
|
this.isLeak = false;
|
||||||
|
this.isDestroy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,6 +103,10 @@ export class Model {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
set(attr: string | object, value?: any) {
|
set(attr: string | object, value?: any) {
|
||||||
|
if(this.isDestroy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(typeof attr === 'object') {
|
if(typeof attr === 'object') {
|
||||||
Object.keys(attr).map(item => {
|
Object.keys(attr).map(item => {
|
||||||
this.set(item, attr[item]);
|
this.set(item, attr[item]);
|
||||||
@ -158,6 +165,10 @@ export class Model {
|
|||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getModelType(): string {
|
||||||
|
return this.modelType;
|
||||||
|
}
|
||||||
|
|
||||||
getId(): string {
|
getId(): string {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
@ -178,6 +189,7 @@ export class Element extends Model {
|
|||||||
|
|
||||||
constructor(id: string, type: string, group: string, layouter: string, sourceElement: SourceElement) {
|
constructor(id: string, type: string, group: string, layouter: string, sourceElement: SourceElement) {
|
||||||
super(id, type);
|
super(id, type);
|
||||||
|
this.modelType = 'element';
|
||||||
|
|
||||||
if(type === null) {
|
if(type === null) {
|
||||||
return;
|
return;
|
||||||
@ -219,6 +231,10 @@ export class Element extends Model {
|
|||||||
SVModelName: this.type
|
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) {
|
constructor(id: string, type: string, element: Element, target: Element, index: number) {
|
||||||
super(id, type);
|
super(id, type);
|
||||||
|
this.modelType = 'link';
|
||||||
|
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
@ -277,6 +295,8 @@ export class Marker extends Model {
|
|||||||
|
|
||||||
constructor(id: string, type: string, label: string | string[], target: Element) {
|
constructor(id: string, type: string, label: string | string[], target: Element) {
|
||||||
super(id, type);
|
super(id, type);
|
||||||
|
this.modelType = 'marker';
|
||||||
|
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
|
||||||
|
@ -106,13 +106,15 @@ import { Container } from "./container";
|
|||||||
protected afterInitRenderer() {
|
protected afterInitRenderer() {
|
||||||
let g6Instance = this.getG6Instance(),
|
let g6Instance = this.getG6Instance(),
|
||||||
marker = null,
|
marker = null,
|
||||||
markerX = null,
|
markerX = 0,
|
||||||
markerY = null,
|
markerY = 0,
|
||||||
dragStartX = null,
|
dragStartX = 0,
|
||||||
dragStartY = null;
|
dragStartY = 0,
|
||||||
|
element = null;
|
||||||
|
|
||||||
g6Instance.on('node:dragstart', ev => {
|
g6Instance.on('node:dragstart', ev => {
|
||||||
const model = ev.item.getModel();
|
const model = ev.item.getModel();
|
||||||
|
element = ev.item.SVModel;
|
||||||
|
|
||||||
if(model.SVModelType === 'marker') {
|
if(model.SVModelType === 'marker') {
|
||||||
return;
|
return;
|
||||||
@ -128,22 +130,33 @@ import { Container } from "./container";
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dragStartX = ev.canvasX;
|
||||||
|
dragStartY = ev.canvasY;
|
||||||
marker = g6Instance.findById(model.markerId);
|
marker = g6Instance.findById(model.markerId);
|
||||||
|
|
||||||
if(marker) {
|
if(marker) {
|
||||||
markerX = marker.getModel().x,
|
markerX = marker.getModel().x,
|
||||||
markerY = marker.getModel().y;
|
markerY = marker.getModel().y;
|
||||||
dragStartX = ev.canvasX;
|
|
||||||
dragStartY = ev.canvasY;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
g6Instance.on('node:dragend', ev => {
|
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;
|
marker = null;
|
||||||
markerX = null,
|
markerX = 0,
|
||||||
markerY = null,
|
markerY = 0,
|
||||||
dragStartX = null,
|
dragStartX = 0,
|
||||||
dragStartY = null;
|
dragStartY = 0;
|
||||||
|
element = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
g6Instance.on('node:drag', ev => {
|
g6Instance.on('node:drag', ev => {
|
||||||
|
@ -21,6 +21,7 @@ export class Renderer {
|
|||||||
private DOMContainer: HTMLElement; // 主可视化视图容器
|
private DOMContainer: HTMLElement; // 主可视化视图容器
|
||||||
private g6Instance; // g6 实例
|
private g6Instance; // g6 实例
|
||||||
|
|
||||||
|
private prevRenderModelList: Model[] = null;
|
||||||
private isFirstRender: boolean; // 是否为第一次渲染
|
private isFirstRender: boolean; // 是否为第一次渲染
|
||||||
|
|
||||||
constructor(engine: Engine, DOMContainer: HTMLElement, g6Options: { [key: string]: any }) {
|
constructor(engine: Engine, DOMContainer: HTMLElement, g6Options: { [key: string]: any }) {
|
||||||
@ -72,12 +73,8 @@ export class Renderer {
|
|||||||
* @param modelList
|
* @param modelList
|
||||||
*/
|
*/
|
||||||
public render(modelList: Model[], removeModels: Model[]) {
|
public render(modelList: Model[], removeModels: Model[]) {
|
||||||
let data: G6Data = Util.convertModelList2G6Data(modelList),
|
const renderModelList = [...modelList, ...removeModels],
|
||||||
removeData: G6Data = Util.convertModelList2G6Data(removeModels),
|
renderData: G6Data = Util.convertModelList2G6Data(renderModelList);
|
||||||
renderData: G6Data = {
|
|
||||||
nodes: [...data.nodes, ...removeData.nodes],
|
|
||||||
edges: [...data.edges, ...removeData.edges]
|
|
||||||
};
|
|
||||||
|
|
||||||
if(this.isFirstRender) {
|
if(this.isFirstRender) {
|
||||||
this.g6Instance.read(renderData);
|
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) {
|
if(this.isFirstRender) {
|
||||||
this.g6Instance.getEdges().forEach(item => item.toFront());
|
this.g6Instance.getEdges().forEach(item => item.toFront());
|
||||||
|
@ -124,7 +124,15 @@ export class ViewManager {
|
|||||||
this.handleFreedLabel(freedElements, prevLayoutGroupTable.get(freedGroupName));
|
this.handleFreedLabel(freedElements, prevLayoutGroupTable.get(freedGroupName));
|
||||||
this.prevFreedElements = freedElements;
|
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 id
|
||||||
* @param callback
|
|
||||||
*/
|
*/
|
||||||
public selectElement(id: string, callback?: (element: Element) => void) {
|
public findElement(id: string) {
|
||||||
const elements = this.getElements();
|
const elements = this.getElements();
|
||||||
const stringId = id.toString();
|
const stringId = id.toString();
|
||||||
const targetElement = elements.find(item => item.sourceId === stringId);
|
const targetElement = elements.find(item => item.sourceId === stringId);
|
||||||
|
|
||||||
if(targetElement) {
|
return targetElement;
|
||||||
callback && callback(targetElement);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -239,7 +236,9 @@ export class Engine {
|
|||||||
return;
|
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