Newer
Older
/**
* 保存序列化的拓扑图JSON数据到服务器
*/
TopologyPanel.prototype.saveTopology = function (url) {
var containers = editor.utils.getContainers()
for (var c = 0; c < containers.length; c++) {
var temp = []
var nodes = containers[c].childs
for (var n = 0; n < nodes.length; n++) {
if (nodes[n] instanceof JTopo.Node) {
temp.push(nodes[n].nodeId)
}
}
containers[c].childNodes = temp.join(',')
}
// 获取json
// 保存拓扑图数据
}
/**
* 重置拓扑图
*/
TopologyPanel.prototype.resetTopology = function (url) {
editor.stageMode = 'normal'
this.replaceStage(url)
}
/**
* 加载指定id的拓扑图JSON数据结构
* @param topologyGuid 拓扑 表记录ID
* @param backImg 拓扑图的背景图片
*/
TopologyPanel.prototype.loadTopology = function (response, topologyGuid, backImg, canvasWidth, canvasHeight) {
// 错误处理
if (!response) {
// 拓扑不存在,创建一个空白的拓扑图
var initTopologyJson = {
'version': '0.4.8',
'wheelZoom': 0.95,
'width': 972,
'height': 569,
'id': 'ST172.19.105.52015100809430700001',
'childs': [
{
'elementType': 'scene',
'id': 'S172.19.105.52015100809430700002',
'translateX': -121.82,
'translateY': 306.72,
'scaleX': 1.26,
'scaleY': 1.26,
'childs': []
editor.init(topologyGuid, backImg, initTopologyJson, canvasWidth, canvasHeight)
editor.init(topologyGuid, backImg, response, canvasWidth, canvasHeight)
}
/**
* 传入JSON形式的拓扑图数据,绘制拓扑图。如果数据结构不正确,返回空拓扑图
* @param topologyJson json形式的拓扑结构数据
* @param backImg 拓扑图的背景图片
*/
TopologyPanel.prototype.loadTopologyByJson = function (topologyJson, backImg) {
try {
JTopo.replaceStageWithJson(topologyJson)
if (editor.stage && editor.scene && editor.scene.childs && editor.scene.childs.length > 0) {
editor.stage.centerAndZoom();
var alarmList = editor.utils.getAllNodes();
if (alarmList[i].alarm == '危险') {
setInterval(function () {
if (alarmList[i].alarm == '危险') {
if (alarmList[i].alarm == '主机被删除,请及时清理') {
setInterval(function () {
if (alarmList[i].alarm == '主机被删除,请及时清理') {
} else if (alarmList[i].alarm == '') {
alarmList[i].alarm = '主机被删除,请及时清理'
if (alarmList[i].alarm == '故障') {
setInterval(function () {
if (alarmList[i].alarm == '故障') {
} else if (alarmList[i].alarm == '') {
alarmList[i].alarm = '故障'
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
'version': '0.4.8',
'wheelZoom': 0.95,
'width': 972,
'height': 569,
'id': 'ST172.19.105.52015100809430700001',
'childs': [
{
'elementType': 'scene',
'id': 'S172.19.105.52015100809430700002',
'translateX': -121.82,
'translateY': 306.72,
'scaleX': 1.26,
'scaleY': 1.26,
'childs': []
}
]
}
JTopo.replaceStageWithJson(initTopologyJson)
if (editor.stage && editor.scene && editor.scene.childs && editor.scene.childs.length > 0) {
editor.stage.centerAndZoom()
}
}
}
/**
* 清空所有节点
*/
TopologyPanel.prototype.deleteAllNodes = function () {
editor.stage.childs.forEach(function (s) {
s.clear()
})
// 连线重置
editor.beginNode = null
editor.link = null
// alert('已清空拓扑图')
}
/**
* 编辑器对象,原型继承拓扑图面板对象,提供编辑器的主要功能
*/
function TopologyEditor() {
// 绘图参数
this.config = {
// Stage属性
stageFrames: 500, // 舞台播放的帧数/秒
defaultScal: 0.95, // 鼠标滚轮缩放比例
eagleEyeVsibleDefault: false, // 是否显示鹰眼对象
// Node属性
nodeAlpha: 1, // 节点透明度,取值范围[0-1]
nodeStrokeColor: '0,0,0', // 节点描边的颜色
nodeFillColor: '0,0,0', // 节点填充颜色
nodeShadow: false, // 节点是否显示阴影
nodeShadowColor: 'rgba(0,0,0,0.5)', // 节点阴影的颜色
nodeFont: '8px Consolas', // 节点字体
nodeFontColor: '0,0,0', // 节点文字颜色,如"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: '177,209,239', // 连线的颜色
linkFillColor: '177,209,239',
linkShadow: false, // 是否显示连线阴影
linkShadowColor: 'rgba(0,0,0,0.5)',
linkDirection: 'horizontal', // 折线的方向
// Container属性
containerAlpha: 1,
containerStrokeColor: '22,124,255',
containerFillColor: '22,124,255',
containerShadow: false,
containerShadowColor: 'rgba(0,0,0,0.5)',
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
this.scene = null
// 当前模式
this.stageMode = 'normal'
// 默认连线类型
this.lineType = 'line'
// 当前选择的节点对象
this.currentNode = null
// 当前选择的连线对象
this.currentLink = null
// 节点右键菜单DOM对象
this.nodeMenu = $('#node-menu')
// 连线右键菜单DOM对象
this.lineMenu = $('#line-menu')
// 全局右键菜单
this.mainMenu = $('#main-menu')
// 布局管理菜单
this.layoutMenu = $('#layout-menu')
// 节点文字方向
this.nodeTextPosMenu = $('#node-text-pos-menu')
// 节点分组菜单
this.groupMangeMenu = $('#group-mange-menu')
// 节点对齐菜单
this.groupAlignMenu = $('#group-align-menu')
this.alignGroup = $('#align-group')
// 分组的容器管理菜单
this.containerMangeMenu = $('#container-mange-menu')
// 调用构造函数,继承TopologyPanel类
TopologyPanel.call(this)
}
// 原型继承
TopologyEditor.prototype = new TopologyPanel()
/**
* 菜单初始化
*/
TopologyEditor.prototype.initMenus = function () {
// 右键菜单事件处理(右键一级菜单)
self.nodeMenu.on('click', function (event) {
// 菜单文字对应事件
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
if (text === '删除节点(Delete)') {
editor.utils.deleteSelectedNodes()
} else if (text === '复制节点(Shift+C)') {
self.utils.cloneSelectedNodes()
} else if (text === '撤销(Shift+Z)') {
self.utils.cancleNodeAction()
} else if (text === '重做(Shift+R)') {
self.utils.reMakeNodeAction()
} else {
editor.utils.saveNodeInitState()
}
switch (text) {
case '放大(Shift+)':
self.utils.scalingBig()
self.utils.saveNodeNewState()
break
case '缩小(Shift-)':
self.utils.scalingSmall()
self.utils.saveNodeNewState()
break
case '顺时针旋转(Shift+U)':
self.utils.rotateAdd()
self.utils.saveNodeNewState()
break
case '逆时针旋转(Shift+I)':
self.utils.rotateSub()
self.utils.saveNodeNewState()
break
case '节点文字':
return
default :
}
// 关闭菜单
$(this).hide()
})
self.nodeMenu.on('mouseover', function (event) {
// 菜单文字
var text = $.trim($(event.target).text())
var menuX = parseInt(this.style.left) + $(document.getElementById('change-node-text-pos')).width()
// 边界判断
if (menuX + self.nodeTextPosMenu.width() * 2 >= self.stage.width) {
menuX -= (self.nodeTextPosMenu.width() + self.nodeMenu.width())
}
if (text === '文字位置') {
self.layoutMenu.hide()
self.nodeTextPosMenu.css({
top: parseInt(this.style.top) + $(document.getElementById('change-node-text-pos')).height(),
left: menuX
}).show()
} else if (text === '应用布局') {
self.nodeTextPosMenu.hide()
self.layoutMenu.css({
top: parseInt(this.style.top),
left: menuX
}).show()
} else {
self.layoutMenu.hide()
self.nodeTextPosMenu.hide()
}
})
// 修改节点文字位置菜单
self.nodeTextPosMenu.on('click', function (event) {
// 菜单文字
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
if (self.currentNode && self.currentNode instanceof JTopo.Node) {
self.utils.saveNodeInitState()
switch (text) {
case '顶部居左':
self.currentNode.textPosition = 'Top_Left'
self.utils.saveNodeNewState()
break
case '顶部居中':
self.currentNode.textPosition = 'Top_Center'
self.utils.saveNodeNewState()
break
case '顶部居右':
self.currentNode.textPosition = 'Top_Right'
self.utils.saveNodeNewState()
break
case '中间居左':
self.currentNode.textPosition = 'Middle_Left'
self.utils.saveNodeNewState()
break
case '居中':
self.currentNode.textPosition = 'Middle_Center'
self.utils.saveNodeNewState()
break
case '中间居右':
self.currentNode.textPosition = 'Middle_Right'
self.utils.saveNodeNewState()
break
case '底部居左':
self.currentNode.textPosition = 'Bottom_Left'
self.utils.saveNodeNewState()
break
case '底部居中':
self.currentNode.textPosition = 'Bottom_Center'
self.utils.saveNodeNewState()
break
case '底部居右':
self.currentNode.textPosition = 'Bottom_Right'
self.utils.saveNodeNewState()
break
default :
}
$('div[id$=\'-menu\']').hide()
}
})
// 连线菜单
self.lineMenu.on('click', function (event) {
// 关闭菜单
$(this).hide()
switch (text) {
case '连线设置':
// alert('连线设置')
break
case '删除连线':
editor.utils.deleteLine()
break
default :
}
})
// 系统设置菜单
self.mainMenu.on('click', function (event) {
// 关闭菜单
$(this).hide()
})
// 节点分组菜单
self.groupMangeMenu.on('click', function (event) {
$(this).hide()
if (text === '新建分组') {
self.utils.toMerge()
}
})
// 对齐
self.groupAlignMenu.on('click', function (event) {
var currNode = self.currentNode
var selectedNodes = self.utils.getSelectedNodes()
if (!currNode || !selectedNodes || selectedNodes.length === 0) return
$(this).hide()
selectedNodes.forEach(function (n) {
if (n.nodeId === currNode.nodeId) return true
if (text === '水平对齐') {
n.y = currNode.y
} else if (text === '垂直对齐') {
n.x = currNode.x
} else {
}
})
})
self.groupMangeMenu.on('mouseover', function (event) {
var menuX = parseInt(this.style.left) + $(document.getElementById('align-group')).width()
if (menuX + self.alignGroup.width() * 2 >= self.stage.width) {
menuX -= (self.alignGroup.width() + self.groupMangeMenu.width())
}
self.groupAlignMenu.css({
top: parseInt(this.style.top) + $(document.getElementById('align-group')).height(),
left: menuX
}).show()
} else {
self.groupAlignMenu.hide()
}
})
// 容器管理菜单
self.containerMangeMenu.on('click', function (event) {
if (!(cNode instanceof JTopo.Container)) {
return
}
$(this).hide()
if (text === '拆分') {
self.utils.toSplit()
self.utils.deleteNode(cNode)
}
})
// 容器管理菜单
self.layoutMenu.on('click', function (event) {
editor.currentNode.layout = {}
$('div[id$=\'-menu\']').hide()
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
if (text === '取消布局') {
editor.currentNode.layout.on = false
} else if (text === '分组布局') {
editor.currentNode.layout.on = true
editor.currentNode.layout.type = 'auto'
} else if (text === '树形布局') {
editor.currentNode.layout.on = true
editor.currentNode.layout.type = 'tree'
editor.currentNode.layout.direction = 'bottom'
editor.currentNode.layout.width = 80
editor.currentNode.layout.height = 100
JTopo.layout.layoutNode(self.scene, self.currentNode, true)
} else if (text === '圆形布局') {
editor.currentNode.layout.on = true
editor.currentNode.layout.type = 'circle'
editor.currentNode.layout.radius = 200
JTopo.layout.layoutNode(self.scene, self.currentNode, true)
}
})
}
/**
* 替换当前舞台,用于编辑保存后重新加载
* @param topologyGuid
*/
TopologyEditor.prototype.replaceStage = function (url) {
// var self = this
$.ajax({
type: 'GET',
url: url,
async: false,
contentType: 'application/json',
dataType: 'json',
error: function () {
// alert('服务器异常,请稍后重试..')
},
success: function (response) {
// 错误处理
if (response.code !== 200) {
console.error(response.msg)
} else {
JTopo.replaceStageWithJson(topologyJson)
if (editor.stage && editor.scene && editor.scene.childs && editor.scene.childs.length > 0) {
editor.stage.centerAndZoom()
}
}
}
})
}
/**
* 编辑器初始化方法,根据请求返回结果加载空白的或者指定结构的拓扑编辑器
* @param topologyGuid 拓扑记录ID
* @param backImg 背景图片
* @param topologyJson 拓扑JSON结构
*/
TopologyEditor.prototype.init = function (topologyGuid, backImg, topologyJson, canvasWidth, canvasHeight) {
// 加载空白的编辑器
if (topologyJson === '-1') {
this.stage = new JTopo.Stage(canvas) // 定义舞台对象
this.scene = new JTopo.Scene(this.stage) // 定义场景对象
} else {
this.stage = JTopo.createStageFromJson(topologyJson, canvas) // 根据保存好的jsonStr(拓扑结构)创建舞台对象
this.scene = this.stage.childs[0] // 场景对象列表,childs是舞台的属性
}
// 滚轮缩放
this.stage.frames = this.config.stageFrames // 设置当前舞台播放的帧数/秒
this.stage.wheelZoom = this.config.defaultScal // 鼠标滚轮缩放操作比例
this.stage.eagleEye.visible = this.config.eagleEyeVsibleDefault // 是否开启鹰眼
this.stage.mode = this.stageMode
// 设置舞台模式
// 背景由样式指定
// this.scene.background = backImg;
// 用来连线的两个节点
this.tempNodeA = new JTopo.Node('tempA')
this.tempNodeA.setSize(1, 1)
this.tempNodeZ = new JTopo.Node('tempZ')
this.tempNodeZ.setSize(1, 1)
this.beginNode = null
this.link = null
// 初始化菜单
this.initMenus()
// 鼠标进入事件
this.scene.mouseover(function (event) {
Timer.start()
// 进入某个节点
if (event.target != null && event.target instanceof JTopo.Node && event.target.description && editor.stageMode !== 'edit') {
var menuY = event.layerY ? event.layerY : event.offsetY
var menuX = event.layerX ? event.layerX : event.offsetX
if (menuX + $('.node-infobox').width() >= self.stage.width) {
menuX -= $('.node-infobox').width()
if (menuY + $('.node-infobox').height() >= self.stage.height) {
menuY -= $('.node-infobox').height()
$('.link-tooltip').css('display', 'none');
$('.node-infobox').css({
'display': 'block',
'margin-top': menuY,
'margin-left': menuX,
'cursor': 'pointer'
})
// 进入某个连线
} else if (event.target != null && event.target instanceof JTopo.Link && event.target.linkTooltip && editor.stageMode !== 'edit') {
$('.link-tooltip span').html(event.target.linkTooltip)
// 记录鼠标触发位置在canvas中的相对位置
var menuY = event.layerY ? event.layerY : event.offsetY
var menuX = event.layerX ? event.layerX : event.offsetX
// 判断边界出是否能完整显示弹出菜单
if (menuX + $('.link-tooltip').width() >= self.stage.width) {
menuX -= $('.link-tooltip').width()
}
if (menuY + $('.link-tooltip').height() >= self.stage.height) {
menuY -= $('.link-tooltip').height()
}
$('.node-tooltip').css('display', 'none')
$('.link-tooltip').css({
'display': 'block',
'margin-top': menuY,
'margin-left': menuX,
'cursor': 'pointer'
})
} else {
// 鼠标进入别的地方
}
})
// 鼠标离开事件
this.scene.mouseout(function (event) {
// 消抖
if (timeSpan > 100) {
$('.node-tooltip').css('display', 'none')
$('.link-tooltip').css('display', 'none')
Timer.stop()
}
})
// 鼠标单击节点事件
this.scene.click(function (event) {
if (!event.target) {
// 单击舞台空白处
$('.node-tooltip').css('display', 'none')
return;
}
self.currentNode = event.target;
// 只读模式下单击节点
if (event.target instanceof JTopo.Node && editor.stageMode === 'normal') {
} else if (event.target instanceof JTopo.Node && editor.stageMode === 'edit') {
} else if (event.target instanceof JTopo.Link && editor.stageMode === 'normal') {
} else if (event.target instanceof JTopo.Link && editor.stageMode === 'edit') {
} else {
// 单击别的地方
$('.node-tooltip').css('display', 'none')
}
})
// 双击编辑事件
this.scene.dbclick(function (event) {
if (!event.target) {
// 单击舞台空白处
$('.node-tooltip').css('display', 'none')
return;
}
self.currentNode = event.target;
if (event.target instanceof JTopo.Node && editor.stageMode === 'normal') {
if(event.target.topoId) window.NeTopologyComponent.component.changeTopo(event.target.topoId);
// 只处理双击节点事件
if (event.target instanceof JTopo.Node && editor.stageMode === 'edit') {
name: event.target.text,
hostId: event.target.hostId,
topoId: event.target.topoId,
};
//打开节点编辑模态框
window.NeTopologyComponent.component.showNodeModal(nodeObj);
} else if (event.target instanceof JTopo.Link && editor.stageMode === 'edit') {
lineObj.hostIds.push(event.target.nodeA.hostId);
lineObj.hostIds.push(event.target.nodeZ.hostId);
//打开连线编辑模态框
window.NeTopologyComponent.component.showLineModal(lineObj);
// 清除起始节点不完整的拖放线
this.scene.mousedown(function (e) {
if (self.link && !self.isSelectedMode && (e.target == null || e.target === self.beginNode || e.target === self.link)) {
this.remove(self.link)
}
})
// 监听鼠标松开事件
// 处理右键菜单、左键连线
// event.button: 0-左键 1-中键 2-右键
this.scene.mouseup(function (event) {
if (event.target && event.target instanceof JTopo.Node) {
self.currentNode = event.target
} else if (event.target && event.target instanceof JTopo.Link) {
self.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 === 2) { // 右键菜单
$('div[id$=\'-menu\']').hide()
var menuY = event.layerY ? event.layerY : event.offsetY
var menuX = event.layerX ? event.layerX : event.offsetX
// 记录鼠标触发位置在canvas中的相对位置
self.xInCanvas = menuX
self.yInCanvas = menuY
if (event.target) {
if (event.target instanceof JTopo.Node) { // 处理节点右键菜单事件
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
// 如果是节点多选状态弹出分组菜单
if (selectedNodes && selectedNodes.length > 1) {
// 判断边界出是否能完整显示弹出菜单
if (menuX + self.groupMangeMenu.width() >= self.stage.width) {
menuX -= self.groupMangeMenu.width()
}
if (menuY + self.groupMangeMenu.height() >= self.stage.height) {
menuY -= self.groupMangeMenu.height()
}
self.groupMangeMenu.css({
top: menuY,
left: menuX
}).show()
} else {
// 判断边界出是否能完整显示弹出菜单
if (menuX + self.nodeMenu.width() >= self.stage.width) {
menuX -= self.nodeMenu.width()
}
if (menuY + self.nodeMenu.height() >= self.stage.height) {
menuY -= self.nodeMenu.height()
}
self.nodeMenu.css({
top: menuY,
left: menuX
}).show()
}
} else if (event.target instanceof JTopo.Link) { // 连线右键菜单
self.lineMenu.css({
top: event.layerY ? event.layerY : event.offsetY,
left: event.layerX ? event.layerX : event.offsetX
}).show()
} else if (event.target instanceof JTopo.Container) { // 容器右键菜单
self.containerMangeMenu.css({
top: event.layerY ? event.layerY : event.offsetY,
left: event.layerX ? event.layerX : event.offsetX
}).show()
}
} else {
// 判断边界出是否能完整显示弹出菜单
if (menuX + self.mainMenu.width() >= self.stage.width) {
menuX -= self.mainMenu.width()
}
if (menuY + self.mainMenu.height() >= self.stage.height) {
menuY -= self.mainMenu.height()
}
self.mainMenu.css({
top: menuY,
left: menuX
}).show()
}
} else if (event.button === 1) { // 中键
} else if (event.button === 0) { // 左键松开事件
if (event.target != null && event.target instanceof JTopo.Node && !self.isSelectedMode && editor.stageMode === 'edit') {
if (self.beginNode == null) {
// 在起始节点处松开鼠标,创建动态的线条(临时节点A-Z)
self.beginNode = event.target
if (self.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.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) {
// 在终点节点处松开鼠标,则建立连线
// 判断两个节点是否有循环引用
/** ***************** 我这里允许循环引用 *************************
for (var el = 0; el < endNode.outLinks.length; el++) {
// 存在循环引用,线条变红
if (endNode.outLinks[el].nodeZ === self.beginNode) {
if (self.link)
this.remove(self.link);
self.beginNode = null;
return;
}
}
*****************************************************************/
// 判断节点间是否有重复连线,即起点到终点有两条以上连线
/** ***************** 我这里允许它有两条连线 *************************
for (var el2 = 0; el2 < self.beginNode.outLinks.length; el2++) {
// 起始节点已经有一条线指向目标节点
if (self.beginNode.outLinks[el2].nodeZ === endNode) {
if (self.link)
this.remove(self.link);
self.beginNode = null;
return;
}
}
*****************************************************************/
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
}
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
link.strokeColor = self.config.linkStrokeColor
link.lineWidth = self.config.linkDefaultWidth
this.add(link)
self.beginNode = null
this.remove(self.link)
self.link = null
} else {
self.beginNode = null
}
} else {
if (self.link) {
this.remove(self.link)
}
self.beginNode = null
}
}
})
// 动态更新连线坐标(创建连线时的临时节点A-Z)
this.scene.mousemove(function (event) {
if (!self.isSelectedMode && self.beginNode) {
self.tempNodeZ.setLocation(event.x, event.y)
}
})
this.scene.mousedrag(function (event) {
if (!self.isSelectedMode && self.beginNode) {
self.tempNodeZ.setLocation(event.x, event.y)
}
})
// 单击编辑器隐藏右键菜单
this.stage.click(function (event) {
if (event.button === 0) {
// 关闭弹出菜单(div)
$('div[id$=\'-menu\']').hide()
}
})
// 鼠标移出舞台
this.stage.mouseout(function (event) {
// 删掉节点带出来的连线
if (self.link && !self.isSelectedMode && (event.target == null || event.target === self.beginNode || event.target === self.link)) {
self.scene.remove(self.link)
}
})
// 按下ctrl进入多选模式,此时选择节点不能画线
$(document).keydown(function (e) {
if (e.shiftKey) { // 组合键模式
switch (e.which) {
case 187:
case 61:
// 单个节点可以撤销操作
if (editor.currentNode instanceof JTopo.Node) {
// 保存初始状态
editor.utils.saveNodeInitState()
editor.utils.scalingBig()
editor.utils.saveNodeNewState()
} else {
editor.utils.scalingBig()
}
break
case 189:
case 173:
if (editor.currentNode instanceof JTopo.Node) {
// 保存初始状态
editor.utils.saveNodeInitState()
editor.utils.scalingSmall()
editor.utils.saveNodeNewState()
} else {
editor.utils.scalingSmall()
}
break
case 70:
editor.utils.showInFullScreen(editor.stage.canvas, 'RequestFullScreen')
break
case 72:
// h 帮助
// alert('帮助文档')
break
case 71:
editor.utils.showInCenter()
break
case 73:
// shif+I 逆时针旋转
if (editor.currentNode instanceof JTopo.Node) {
editor.utils.saveNodeInitState()
editor.utils.rotateSub()
editor.utils.saveNodeNewState()
}
break
case 67:
editor.utils.cloneSelectedNodes()
break
case 80:
editor.utils.showPic()
break
case 82:
// 单个节点重做
if (editor.currentNode instanceof JTopo.Node) {
editor.utils.reMakeNodeAction()
}
break
case 83:
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
editor.saveTopology(true)
break
case 85:
// shif+U 顺时针旋转
if (editor.currentNode instanceof JTopo.Node) {
editor.utils.saveNodeInitState()
editor.utils.rotateAdd()
editor.utils.saveNodeNewState()
}
break
case 87:
// alert('ctrl + w 另存为')
break
case 89:
// ctrl+y
editor.utils.clearTopology()
break
case 90:
// 单个节点撤销
if (editor.currentNode instanceof JTopo.Node) {
editor.utils.cancleNodeAction()
}
break
}
} else if (e.which === 46) { // 单独按下delete
editor.utils.deleteSelectedNodes()
} else if (e.which === 17) { // 单独按下ctrl
self.isSelectedMode = true
}
})
$(document).keyup(function (e) {
if (e.which === 17) {
self.isSelectedMode = false
return false
}
})
// 第一次进入拓扑编辑器,生成stage和scene对象
if (topologyJson === '-1') {
this.saveTopology(false)
}
}
/**
* 图元拖放功能实现
* @param modeDiv 备选列表中的元素(各种样式的节点)
* @param drawArea 舞台区域
*/
TopologyEditor.prototype.drag = function (modeDiv, drawArea, text) {
if (!text) text = ''
// 拖拽开始,携带必要的参数
modeDiv.ondragstart = function (event) {
event = event || window.event
var dragSrc = this
var backImg = $(dragSrc).find('img').eq(0).attr('data-src')