Commit 614773d0 authored by wangqinghua's avatar wangqinghua

update

parent f10fda0f
<div #topologyBody class="topologyBody">
<canvas class="topology-context" id="topology-canvas" #topologyCanvas style="height: 580px;width: 100%">
您的浏览器不支持HTML5!
</canvas>
</div>
import {Component, ElementRef, EventEmitter, HostListener, OnInit, Output, ViewChild} from '@angular/core';
declare let JTopo:any;
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
/**
* 提供拓扑图面板相关操作的函数集,编辑器继承其全部功能
*/
export class JtopoComponent implements OnInit{
@Output() clickNode = new EventEmitter<any>();
@Output() clickLink = new EventEmitter<any>();
@ViewChild('topologyCanvas') topologyCanvas: ElementRef;
@ViewChild('topologyBody') topologyBody: ElementRef;
json = {
"version": "0.4.8",
"wheelZoom": "0.95",
"id": "ST172.19.105.52015100809430700001",
"childs": [
{
"id": "S172.19.105.52015100809430700002",
"elementType": "scene",
"translateX": "106.5",
"translateY": "20",
"scaleX": "1",
"scaleY": "1",
"childs": [
{
"id": "L172.19.105.52015100811153300001",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "1136300297928.587",
"nodeDst": "1406176935353.6848",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811153300002",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "1394105924967.951",
"nodeDst": "1136300297928.587",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811153300004",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "564241624829.4331",
"nodeDst": "318016674603.1266",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811153300005",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "1062340763210.1544",
"nodeDst": "564241624829.4331",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811153300006",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "564241624829.4331",
"nodeDst": "488323736331.2087",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811153300007",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "564241624829.4331",
"nodeDst": "827722371280.0199",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811153300008",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "564241624829.4331",
"nodeDst": "1045863334277.662",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811153300009",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "1262070648024.5728",
"nodeDst": "564241624829.4331",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811153300010",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "1262070648024.5728",
"nodeDst": "1136300297928.587",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811214600001",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "253209434749.73596",
"nodeDst": "564241624829.4331",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811214600002",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "253209434749.73596",
"nodeDst": "1136300297928.587",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811214600003",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "520008948580.8119",
"nodeDst": "564241624829.4331",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811214600004",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "520008948580.8119",
"nodeDst": "1136300297928.587",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811512000002",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "809054608657.865",
"nodeDst": "1394105924967.951",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100811512000004",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "1250687739831.9912",
"nodeDst": "1062340763210.1544",
"lineType": "line",
"zindex": "2"
},
{
"id": "L172.19.105.52015100911051100001",
"elementType": "link",
"x": "0",
"y": "0",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "undefined",
"nodeSrc": "564241624829.4331",
"nodeDst": "597645745716.1871",
"lineType": "line",
"zindex": "2"
},
{
"elementType": "node",
"x": "198",
"y": "315",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "attack-network",
"textPosition": "Bottom_Center",
"nodeId": "1136300297928.587",
"nodeType": "EC",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100809465000001",
"elementType": "node",
"x": "196",
"y": "242",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "attackr-router",
"textPosition": "Bottom_Center",
"nodeId": "1394105924967.951",
"nodeType": "VR",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100809500700002",
"elementType": "node",
"x": "104",
"y": "383.5",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "attack-client",
"textPosition": "Bottom_Center",
"nodeId": "1406176935353.6848",
"nodeType": "VM",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100810295700002",
"elementType": "node",
"x": "539",
"y": "321.5",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "intert-networker",
"textPosition": "Bottom_Center",
"nodeId": "564241624829.4331",
"nodeType": "EC",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100810320100002",
"elementType": "node",
"x": "719",
"y": "160.5",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "ws-manage",
"textPosition": "Bottom_Center",
"nodeId": "318016674603.1266",
"nodeType": "VM",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100810402700002",
"elementType": "node",
"x": "725",
"y": "225.5",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "ws-browser",
"textPosition": "Bottom_Center",
"nodeId": "488323736331.2087",
"nodeType": "VM",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100810461200002",
"elementType": "node",
"x": "726",
"y": "293.5",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "internal-mssql",
"textPosition": "Bottom_Center",
"nodeId": "827722371280.0199",
"nodeType": "VM",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100810485100002",
"elementType": "node",
"x": "726",
"y": "361.5",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "internal-ossec",
"textPosition": "Bottom_Center",
"nodeId": "1045863334277.662",
"nodeType": "VM",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100810523500002",
"elementType": "node",
"x": "369",
"y": "245.5",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "internet-www",
"textPosition": "Bottom_Center",
"nodeId": "1262070648024.5728",
"nodeType": "ECVR",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100811153300003",
"elementType": "node",
"x": "536",
"y": "237.5",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "intert-router",
"textPosition": "Bottom_Center",
"nodeId": "1062340763210.1544",
"nodeType": "VR",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100811163200002",
"elementType": "node",
"x": "367.5",
"y": "320",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "internet-blog",
"textPosition": "Bottom_Center",
"nodeId": "253209434749.73596",
"nodeType": "ECVR",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100811204100002",
"elementType": "node",
"x": "370.5",
"y": "403",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "internet-vpn",
"textPosition": "Bottom_Center",
"nodeId": "520008948580.8119",
"nodeType": "ECVR",
"nodeParams": {},
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100811512000001",
"elementType": "node",
"x": "194.5",
"y": "166",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "attack-firewall",
"textPosition": "Bottom_Center",
"nodeId": "809054608657.865",
"nodeType": "FW",
"nodeParams": {},
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100811512000003",
"elementType": "node",
"x": "534.5",
"y": "163",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "intert-firewall",
"textPosition": "Bottom_Center",
"nodeId": "1250687739831.9912",
"nodeType": "FW",
"nodeParams": {},
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
},
{
"id": "N172.19.105.52015100911045400002",
"elementType": "node",
"x": "727.5",
"y": "430",
"width": "32",
"height": "32",
"rotate": "0",
"scaleX": "1",
"scaleY": "1",
"text": "defend-client",
"textPosition": "Bottom_Center",
"nodeId": "597645745716.1871",
"nodeType": "VM",
"nodeImage": "http://10.10.38.99:8888/file/icon/15474547275540202.png",
"zindex": "3"
}
]
}
]
};
utils;
config = {
// Stage属性
stageFrames: 500, // 舞台播放的帧数/秒
defaultScal: 0.95, // 鼠标滚轮缩放比例
eagleEyeVsibleDefault: false, // 是否显示鹰眼对象
// Node属性
nodeAlpha: 1, // 节点透明度,取值范围[0-1]
nodeStrokeColor: '22,124,255', // 节点描边的颜色
nodeFillColor: '255,222,173', // 节点填充颜色
nodeShadow: false, // 节点是否显示阴影
nodeShadowColor: 'rgba(0,0,0,0.5)', // 节点阴影的颜色
nodeFont: '12px Consolas', // 节点字体
nodeFontColor: 'black', // 节点文字颜色,如"255,255,0"
nodeDefaultWidth: 32, // 新建节点默认宽
nodeDefaultHeight: 32, // 新建节点默认高
nodeBorderColor: 'black', // 节点容器边框颜色,如"255,255,0"
nodeBorderRadius: 30, // 节点半径,非圆节点有此属性会变形
nodeRotateValue: 0.5, // 节点旋转的角度(弧度)
nodeScale: 0.2, // 节点缩放幅度(此处保证X和Y均等缩放)
// Link属性
linkAlpha: 1, // 连线透明度,取值范围[0-1]
linkStrokeColor: '0,0,0', // 连线的颜色
linkFillColor: '0,0,0',
linkShadow: false, // 是否显示连线阴影
linkShadowColor: 'rgba(0,0,0,0.5)',
linkFont: '12px Consolas', // 节点字体
linkFontColor: 'black', // 连线文字颜色,如"255,255,0"
linkArrowsRadius: 0, // 线条箭头半径
linkDefaultWidth: 3, // 连线宽度
linkOffsetGap: 80, // 折线拐角处的长度
linkDirection: 'vertical', // 折线的方向
// Container属性
containerAlpha: 1,
containerStrokeColor: '22,124,255',
containerFillColor: '22,124,255',
containerShadow: false,
containerShadowColor: 'rgba(0,0,0,0.5)',
containerFont: '12px Consolas',
containerFontColor: 'black',
containerBorderColor: 'black',
containerBorderRadius: 30,
arrowsRadius:null
};
// 布局参数
layout = {};
// 绘图区属性
stage = null;
scene = null;
// 当前模式
stageMode = 'edit';
// 默认连线类型
lineType = 'line';
// 当前选择的节点对象
currentNode = null;
// 当前选择的连线对象
currentLink = null;
beginNode = null;
link = null;
isSelectedMode;
tempNodeA = new JTopo.Node('tempA');
tempNodeZ = new JTopo.Node('tempZ');
constructor(){}
ngOnInit(){
this.init('assets/img/backimg.png',this.json);
}
/**
* 编辑器初始化方法,根据请求返回结果加载空白的或者指定结构的拓扑编辑器
* @param backImg 背景图片
* @param topologyJson 拓扑JSON结构
*/
init(backImg, topologyJson){
if(!topologyJson){
return;
}
let canvas = this.topologyCanvas.nativeElement;
canvas.width = this.topologyBody.nativeElement.clientWidth;
canvas.height = this.topologyBody.nativeElement.clientHeight;
this.tempNodeA.setSize(1,1);
this.tempNodeZ.setSize(1,1);
let self = this;
if(topologyJson === '-1'){
this.stage = new JTopo.Stage(canvas); //定义舞台对象
this.scene = new JTopo.Scene(this.stage); //定义场景对象
}else{
this.stage = JTopo.createStageFromJson(topologyJson,canvas);
this.scene = this.stage.childs[0];
}
this.getAllNodes()[0].alarm = "告警";
this.scene.mouseover(event=>{
//进入某个节点
// if(event.target != null && event.target instanceof JTopo.Node && event.target.nodeTooltip &&)
});
this.scene.click(event=>{
if(!event.target){
//单击空白处
return;
}
if(event.target instanceof JTopo.Node && this.stageMode === 'normal'){
}else if(event.target instanceof JTopo.Node && this.stageMode === 'edit'){
}else if(event.target instanceof JTopo.Link && this.stageMode === 'normal'){
}else if(event.target instanceof JTopo.Link && this.stageMode === 'edit'){
}
});
//双击编辑事件
this.scene.dbclick(event=>{
if(!event.target){
//双击空白处
return;
}
this.currentNode = event.target;
if(event.target instanceof JTopo.Node && this.stageMode === 'normal'){
}else if(event.target instanceof JTopo.Node && this.stageMode === 'edit'){
console.log(event.target);
}else if(event.target instanceof JTopo.Link && this.stageMode === 'normal'){
}else if(event.target instanceof JTopo.Link && this.stageMode === 'edit'){
console.log(event.target);
}
})
//清楚起始节点不完整的拖放线
this.scene.mousedown(event=>{
if(!event.target){
return;
}
if(this.link && !this.isSelectedMode && (event.target == null || event.target === this.beginNode || event.target === this.link)){
this.scene.remove(this.link);
}
});
//监听鼠标松开事件;
//处理右键菜单、左键连线
//event.button: 0-左键 1-中键 2-右键
this.scene.mouseup(event=>{
if (event.target && event.target instanceof JTopo.Node) {
this.currentNode = event.target
} else if (event.target && event.target instanceof JTopo.Link) {
this.currentLink = event.target
}
if (event.target && event.target instanceof JTopo.Node && event.target.layout && event.target.layout.on && event.target.layout.type && event.target.layout.type !== 'auto') {
JTopo.layout.layoutNode(this, event.target, true, event)
}
if(event.button === 0){
if (event.target != null && event.target instanceof JTopo.Node && !this.isSelectedMode && this.stageMode === 'edit') {
if (this.beginNode == null) {
// 在起始节点处松开鼠标,创建动态的线条(临时节点A-Z)
this.beginNode = event.target;
if (this.lineType === 'line') {
// 直线
self.link = new JTopo.Link(self.tempNodeA, self.tempNodeZ);
self.link.lineType = 'line'
} else if (self.lineType === 'foldLine') {
// 折线
self.link = new JTopo.FoldLink(self.tempNodeA, self.tempNodeZ);
self.link.lineType = 'foldLine';
self.link.direction = self.config.linkDirection
} else if (self.lineType === 'flexLine') {
// 二次折线
self.link = new JTopo.FlexionalLink(self.tempNodeA, self.tempNodeZ);
self.link.direction = self.config.linkDirection;
self.link.lineType = 'flexLine'
} else if (self.lineType === 'curveLine') {
// 曲线
self.link = new JTopo.CurveLink(self.tempNodeA, self.tempNodeZ);
self.link.lineType = 'curveLine'
}
self.link.dashedPattern = 2;
self.link.lineWidth = self.config.linkDefaultWidth;
self.link.shadow = self.config.linkShadow;
self.link.strokeColor = JTopo.util.randomColor();
this.scene.add(self.link);
self.tempNodeA.setLocation(event.x, event.y);
self.tempNodeZ.setLocation(event.x, event.y);
} else if (event.target && event.target instanceof JTopo.Node && self.beginNode !== event.target) {
// 在终点节点处松开鼠标,则建立连线
let endNode = event.target;
let link;
if (self.lineType === 'line') {
link = new JTopo.Link(self.beginNode, endNode);
link.lineType = 'line'
} else if (self.lineType === 'foldLine') {
link = new JTopo.FoldLink(self.beginNode, endNode);
link.direction = self.config.linkDirection;
link.bundleOffset = self.config.linkOffsetGap; // 折线拐角处的长度
link.lineType = 'foldLine'
} else if (self.lineType === 'flexLine') {
link = new JTopo.FlexionalLink(self.beginNode, endNode);
link.direction = self.config.linkDirection;
link.lineType = 'flexLine';
link.offsetGap = self.config.linkOffsetGap;
} else if (self.lineType === 'curveLine') {
link = new JTopo.CurveLink(self.beginNode, endNode);
link.lineType = 'curveLine';
}
// 保存线条所连接的两个节点ID
link.nodeSrc = self.beginNode.nodeId;
link.nodeDst = endNode.nodeId;
if (self.lineType !== 'curveLine') {
link.arrowsRadius = self.config.arrowsRadius;
}
link.strokeColor = self.config.linkStrokeColor;
link.lineWidth = self.config.linkDefaultWidth;
console.log(this);
this.scene.add(link);
self.beginNode = null;
this.scene.remove(self.link);
self.link = null;
} else {
self.beginNode = null;
}
} else {
if (this.link) {
console.log(this);
this.scene.remove(this.link);
}
this.beginNode = null;
}
}
});
//动态更新连线坐标
this.scene.mousemove(event=>{
if(!self.isSelectedMode && self.beginNode){
self.tempNodeA.setLocation(event.x,event.y);
}
});
this.scene.mousedrag(event=>{
if (!self.isSelectedMode && self.beginNode) {
self.tempNodeZ.setLocation(event.x, event.y)
}
});
//鼠标移出舞台
this.stage.mouseout(event=>{
// 删掉节点带出来的连线
if (self.link && !self.isSelectedMode && (event.target == null || event.target === self.beginNode || event.target === self.link)) {
self.scene.remove(self.link)
}
})
this.scene.background = backImg;
}
//键盘事件
@HostListener('window:keyup',['$event'])
keyEvent(e:KeyboardEvent){
if (e.shiftKey) { // 组合键模式
switch (e.which) {
// 放大 ctrl+=
case 187:
case 61:
// 单个节点可以撤销操作
if (this.currentNode instanceof JTopo.Node) {
// 保存初始状态
this.utils.saveNodeInitState();
this.utils.scalingBig();
this.utils.saveNodeNewState();
} else {
this.utils.scalingBig();
}
break;
// 缩小 ctrl+-
case 189:
case 173:
if (this.currentNode instanceof JTopo.Node) {
// 保存初始状态
this.utils.saveNodeInitState();
this.utils.scalingSmall();
this.utils.saveNodeNewState();
} else {
this.utils.scalingSmall();
}
break
case 70:
// ctrl+f 全屏显示
this.utils.showInFullScreen(this.stage.canvas, 'RequestFullScreen')
break;
case 72:
// h 帮助
// alert('帮助文档')
break;
case 71:
// ctrl+g 居中显示
this.utils.showInCenter();
break;
case 73:
// shif+I 逆时针旋转
if (this.currentNode instanceof JTopo.Node) {
this.utils.saveNodeInitState();
this.utils.rotateSub();
this.utils.saveNodeNewState();
}
break;
case 67:
this.utils.cloneSelectedNodes();
break;
case 80:
// ctrl + p
this.utils.showPic();
break;
case 82:
// 单个节点重做
if (this.currentNode instanceof JTopo.Node) {
this.utils.reMakeNodeAction();
}
break;
case 83:
// ctrl+s 保存
this.saveTopology(true);
break;
case 85:
// shif+U 顺时针旋转
if (this.currentNode instanceof JTopo.Node) {
this.utils.saveNodeInitState();
this.utils.rotateAdd();
this.utils.saveNodeNewState()
}
break;
case 87:
// alert('ctrl + w 另存为')
break
case 89:
// ctrl+y
this.utils.clearTopology();
break
case 90:
// 单个节点撤销
if (this.currentNode instanceof JTopo.Node) {
this.utils.cancleNodeAction()
}
break
}
} else if (e.which === 46) { // 单独按下delete
this.utils.deleteSelectedNodes()
} else if (e.which === 17) { // 单独按下ctrl
this.isSelectedMode = true
}
}
/**
* 图元拖放功能实现
* @param modeDiv 备选列表中的元素(各种样式的节点)
* @param drawArea 舞台区域
*/
drag(modeDiv, drawArea, text){
if(!text){
text = '';
}
let self = this;
// 拖拽开始,携带必要的参数
modeDiv.ondragstart = (event)=> {
event = event || window.event;
let dragSrc = this;
// let backImg = $(dragSrc).find('img').eq(0).attr('src')
// backImg = backImg.substring(backImg.lastIndexOf('/') + 1)
// let nodeType = $(this).attr('topo-nodetype')
try {
// IE只允许KEY为text和URL
// event.dataTransfer.setData('text', backImg + ';' + text + ';' + nodeType)
} catch (ex) {
console.log(ex)
}
};
// 阻止默认事件
drawArea.ondragover = (event)=> {
event.preventDefault();
return false
};
// 创建节点
drawArea.ondrop = (event)=> {
// 只读模式
if (this.stageMode === "normal") {
return;
}
event = event || window.event;
let data = event.dataTransfer.getData('text');
let img, text, nodeType;
if (data) {
let datas = data.split(';');
if (datas && datas.length === 3) {
img = datas[0];
text = datas[1];
nodeType = datas[2];
let node = new JTopo.Node();
node.fontColor = self.config.nodeFontColor;
// 节点坐标
node.setBound((event.layerX ? event.layerX : event.offsetX) - self.scene.translateX - self.config.nodeDefaultWidth / 2,
(event.layerY ? event.layerY : event.offsetY) - self.scene.translateY - self.config.nodeDefaultHeight / 2, self.config.nodeDefaultWidth, self.config.nodeDefaultHeight);
// 节点图片
node.setImage( img);
// 节点数据
node.nodeId = generateUUID;
node.nodeType = nodeType;
node.text = text;
node.nodeImage = img;
self.scene.add(node);
self.currentNode = node;
}
}
}
}
/**
* 保存序列化的拓扑图成json
*/
saveTopology(url){
let self = this;
// 保存container状态
let containers = this.getContainers();
for (let c = 0; c < containers.length; c++) {
let temp = [];
let nodes = containers[c].childs;
for (let n = 0; n < nodes.length; n++) {
if (nodes[n] instanceof JTopo.Node) {
temp.push(nodes[n].nodeId)
}
}
containers[c].childNodes = temp.join(',')
}
// 获取json
let topologyJSON = this.stage.toJson();
console.log(topologyJSON);
}
/**
* 重置拓扑图
*/
resetTopology(){
}
/**
* 传入JSON形式的拓扑图数据,绘制拓扑图。如果数据结构不正确,返回空拓扑图
* @param topologyJson json形式的拓扑结构数据
* @param backImg 拓扑图的背景图片
*/
loadTopologyByJson(topologyJson, backImg){
this.init(backImg,topologyJson);
}
//工具方法
/**
* 清空所有节点
*/
deleteAllNodes(){
this.stage.childs.forEach(s=>{
s.clear();
});
this.beginNode = null;
this.link = null;
}
//编辑模式
editTopology(){
this.stageMode = 'edit';
console.log(this);
}
//只读模式
normalTopology(){
this.stageMode = 'normal';
}
//添加节点
addNode(img,text){
if(this.stageMode === 'normal'){
return;
}
if(!img){
img = 'icon_virtual_host.png'; //默认图片
}
if(!text){
text = '主机';
}
let node = new JTopo.Node();
node.fontColor = this.config.nodeFontColor;
//节点坐标
node.setBound(20,20,50,50);
//默认图片
node.setImage(img);
//节点数据
node.nodeId = generateUUID;
node.text = text;
node.nodeImage = img;
this.scene.add(node);
}
//获取所以容器的内容
getContainers(){
let containers = [];
this.stage.childs.forEach( (s) =>{
s.childs.forEach((n)=> {
if(n.elementType === 'container') {
containers.push(n)
}
})
});
return containers;
}
// 获取所有节点
getAllNodes() {
return this.stage.find('node');
}
// 获取所有选择的节点实例
getSelectedNodes() {
let selectedNodes = [];
let nodes = this.scene.selectedElements;
nodes.forEach( (n)=> {
if (n.elementType === 'node') {
selectedNodes.push(n)
}
});
return selectedNodes
}
// 节点分组合并
toMerge() {
let selectedNodes = this.getSelectedNodes();
// 不指定布局的时候,容器的布局为自动(容器边界随元素变化)
let container = new JTopo.Container();
container.textPosition = 'Top_Center';
container.fontColor = this.config.nodeFontColor;
container.borderColor = this.config.nodeBorderColor;
container.borderRadius = this.config.nodeBorderRadius;
this.scene.add(container);
selectedNodes.forEach( (n)=> {
container.add(n)
})
}
// 分组拆除
toSplit() {
if (this.currentNode instanceof JTopo.Container) {
this.currentNode.removeAll();
this.scene.remove(this.currentNode)
}
}
// 删除连线
deleteLine() {
if (this.currentNode instanceof JTopo.Link) {
this.scene.remove(this.currentNode);
// if (this.currentNode.id)
// this.deleteNodeById(this.currentNode.id, "link");
this.currentNode = null;
}
}
// 删除节点
deleteNode(n) {
this.scene.remove(n);
// if (n.id)
// this.deleteNodeById(n.id, n.elementType, n.dataType);
this.currentNode = null;
// 连线重置
this.beginNode = null;
if (this.link) {
this.scene.remove(this.link)
}
this.link = null
}
// 删除选择的节点
deleteSelectedNodes() {
if (this.stageMode !== 'edit') {
return false
}
let self = this;
let nodes = this.scene.selectedElements;
if (nodes && nodes.length > 0) {
for (let i = 0; i < nodes.length; i++) {
self.deleteNode(nodes[i])
}
}
}
//设置
// 放大
scalingBig() {
if (this.currentNode instanceof JTopo.Node) {
this.currentNode.scaleX += this.config.nodeScale;
this.currentNode.scaleY += this.config.nodeScale;
} else {
this.stage.zoomOut(this.stage.wheelZoom)
}
}
// 缩小
scalingSmall() {
if (this.currentNode instanceof JTopo.Node) {
this.currentNode.scaleX -= this.config.nodeScale;
this.currentNode.scaleY -= this.config.nodeScale
} else {
this.stage.zoomIn(this.stage.wheelZoom);
}
}
// 顺时针旋转
rotateAdd() {
if (this.currentNode instanceof JTopo.Node) {
this.currentNode.rotate += this.config.nodeRotateValue
}
}
// 逆时针旋转
rotateSub() {
if (this.currentNode instanceof JTopo.Node) {
this.currentNode.rotate -= this.config.nodeRotateValue
}
}
// 清空编辑器
clearTopology() {
// 删除节点表对应的节点记录
this.deleteAllNodes()
}
// 拓扑图预览
showPic() {
this.stage.saveImageInfo()
}
exportAsImage() {
this.stage.exportAsImage()
}
setEditMode() {
this.stageMode = 'edit'
}
setNormalMode() {
this.stageMode = 'normal'
}
// 复制节点
cloneNode(n) {
if (n instanceof JTopo.Node) {
let newNode = new JTopo.Node();
n.serializedProperties.forEach( (i)=> {
// 只复制虚拟机的模板属性
// if (i == "templateId" && n.dataType != "VM") return true;
newNode[i] = n[i]
})
newNode.nodeId = generateUUID;
newNode.alpha = this.config.nodeAlpha;
newNode.strokeColor = this.config.nodeStrokeColor;
newNode.fillColor = this.config.nodeFillColor;
newNode.shadow = this.config.nodeShadow;
newNode.shadowColor = this.config.nodeShadowColor;
newNode.font = this.config.nodeFont;
newNode.fontColor = this.config.nodeFontColor;
newNode.borderRadius = null;
newNode.layout = n.layout;
newNode.selected = false;
// var deviceNum = ++this.modeIdIndex;
// newNode.deviceId = "device" + deviceNum;
newNode.setLocation(n.x + n.width, n.y + n.height);
newNode.text = n.text;
newNode.setImage(n.image);
this.scene.add(newNode);
}
}
// 复制选择的节点
cloneSelectedNodes() {
let self = this;
let nodes = this.scene.selectedElements;
nodes.forEach((n)=> {
if (n.elementType === 'node') {
self.cloneNode(n)
}
})
}
// 全屏显示
showInFullScreen(element, method) {
let usablePrefixMethod;
['webkit', 'moz', 'ms', 'o', ''].forEach( (prefix)=> {
if (usablePrefixMethod) {
return
}
if (prefix === '') {
// 无前缀,方法首字母小写
// method = method.slice(0, 1).toLowerCase() + method.slice(1)
}
let typePrefixMethod = typeof element[prefix + method];
if (typePrefixMethod + '' !== 'undefined') {
if (typePrefixMethod === 'function') {
usablePrefixMethod = element[prefix + method]();
} else {
usablePrefixMethod = element[prefix + method];
}
}
}
)
return usablePrefixMethod
}
// 居中显示
showInCenter() {
this.stage.centerAndZoom()
}
// 根据指定的key返回节点实例
getNodeByKey(key, value) {
let node = null
this.stage.childs.forEach( (s)=> {
s.childs.forEach( (n)=> {
if (n.elementType === 'node' && n[key] === value) {
node = n
return node
}
})
});
return node
}
// 撤销对节点的操作
cancleNodeAction() {
if (this.currentNode.currStep <= 0) {
return
}
--this.currentNode.currStep;
for (let p in this.currentNode) {
if (p !== 'currStep') {
this.currentNode[p] = (this.currentNode.historyStack[this.currentNode.currStep])[p]
}
}
}
// 重做节点操作
reMakeNodeAction() {
if (this.currentNode.currStep >= this.currentNode.maxHistoryStep ||
this.currentNode.currStep >= this.currentNode.historyStack.length - 1) {
return
}
this.currentNode.currStep++
for (let q in this.currentNode) {
if (q !== 'currStep') {
this.currentNode[q] = (this.currentNode.historyStack[this.currentNode.currStep])[q]
}
}
}
// 保存节点新的状态
saveNodeNewState() {
// 如果历史栈超过最大可记录历史长度,丢弃第一个元素
if (this.currentNode.historyStack.length >= this.currentNode.maxHistoryStep + 1) {
this.currentNode.historyStack.shift()
}
this.currentNode.historyStack.push(JTopo.util.clone(this.currentNode))
this.currentNode.currStep = this.currentNode.historyStack.length - 1
}
// 保存节点初始状态,便于回退
saveNodeInitState() {
if (!this.currentNode.hasInitStateSaved) {
this.currentNode.historyStack.push(JTopo.util.clone(this.currentNode))
this.currentNode.hasInitStateSaved = true
}
}
// 取消出参数节点外所有节点的选中状态
unSelectAllNodeExcept(node) {
this.stage.childs.forEach( (s)=> {
s.childs.forEach( (n)=> {
// id属性无有效值,说明该节点没有保存到数据库
if (n.nodeId !== node.nodeId) {
n.selected = false
}
})
})
}
}
export class generateUUID{
constructor(){
let d = new Date().getTime();
let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c)=> {
let r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
});
return uuid
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment