初稿:https://blog.csdn.net/qq_44941500/article/details/105021135
let svgRoot = SVG('box-workarea').id('svgroot').size('3000px','1500px').attr('style','background-color:white').addClass('noselectText') // 画板svg根对象
let svgRootGroup = svgRoot.group().id('svgRootGroup')
let svgComponent = new SvgComponent; // 器件组管理对象
var svgmenu = new menu(); // 菜单对象
var selectCmpt = null; // 选中单个器件
var selectCmpts = []; // 选中多个器件
var selectLines = null; // 选中的连线
var selectPolylines = []; // 选中多条连线
var originScale = 1; // 原始比例
var isComplatePath = true; // 绘制连线
var changeLineX = false; // 连线X变向
var changeLineY = false; // 连线Y变向
var isAddCmpt = false; // 是否处于添加器件状态
var activeCmpt = null; // 刚添加器件
var isSelectBox = false;// 矩形拉选
var isMulSelect = false;// 是否处于多选状态
var isMoveMulSelect = false; // 是否开启批量移动
var isEditPolyline = false; // 是否进入编辑连线状态
var editPolyLine = null; // 编辑连线对象
var currentMousePointer = {}; // 当前点击的点坐标
var currentFootTransform = null; // 当前器件变换矩阵
var currentPolyline = null; // 当前连线
var currentPolylineObj = null; // 当前连线对象
var gridNumber = 10; //栅格数(移动步长)
var svgWidth = 0;
var svgHeight =0;
var svgPolyLineNum = 0;
var defs = svgRoot.defs()
var outpattern = defs.pattern(10, 10, function(add) {
add.path('M 10 0 L 0 0 0 10').fill('none').stroke({color:'#eee',width:0.5})
add.pattern(10,10,function(add){
add.rect().attr({width:10,height:10,fill:'url(#smallGrid)'})
add.path('M 100 0 L 0 0 0 100').fill('none').stroke({color:'#eee',width:1})
}).attr({'id':'grid'})
}).attr({'id':'smallGrid'})
var gridRect = svgRootGroup.rect().size('3000px','1500px').fill('url(#grid)').id('gridrect') // 网格
svgRootGroup.add(gridRect)
var polylineGroup = svgRootGroup.group().id('polylinegroup') // 连线组对象
var crossLine_X = svgRoot.path('M 0 0').attr({'id':'cross_line_x','stroke-dasharray':'2,2', 'fill':'none','stroke':'red', 'stroke-width':1})
var crossLine_Y = svgRoot.path('M 0 0').attr({'id':'cross_line_y','stroke-dasharray':'2,2', 'fill':'none','stroke':'red', 'stroke-width':1})
var selectRectBox = svgRoot.rect('0,0').attr({'id':'select_rect_box','stroke-dasharray':'3,3','fill':'none','stroke':'#0000ff','stroke-width':1}).hide()
mousedown、mouseup(移动结束或连线结束)、mousewheel(放大和缩小)、mousemove(移动)、keyup(鼠标按键)、mouseenter(移动画板时触发)、mouseleave(离开画板时触发)
// 格子缩放计算
function changeGrid(num) {
return Math.round(num/gridNumber)*gridNumber;
}
//画布键盘相应事件
$(document).on('keyup',function (e) {
switch (e.keyCode) {
// 删除选中的器件
case 46:removeSelect();break;
case 82:selectCmpt.rotateCmpt();break;
}
})
// 右键菜单事件
$('#svgroot').on("contextmenu",function(e){
if(isAddCmpt){
activeCmpt.group.remove()
activeCmpt.group = null
isAddCmpt = false;
activeCmpt = null;
return false;
}
if (!isComplatePath && currentPolyline != null){
var points = currentPolyline.attr('points').split(' ')
var l = points.length
// 仅剩起点
if (l <= 3) {
currentPolyline.remove()
currentPolylineObj.startCmpt.circuitMap.delete('startFoot_'+currentPolylineObj.startFoot.attr('id')+'_'+svgPolyLineNum)
svgComponent.finishLine(false)
return false;
}
// 添加的点
points.splice(l-1,1)
currentPolyline.attr('points',points)
return false;
}
// 显示快捷菜单
if(selectCmpt !=null){
svgmenu.selectCmptMenu(selectCmpt)
selectCmpts.push(selectCmpt)
}
$('#svgmenu').menu('show', {
left: e.pageX,
top: e.pageY,
hideOnUnhover: false,
noline:false
});
currentMousePointer.x = e.offsetX
currentMousePointer.y = e.offsetY
return false
});
// 取消选择器件 + 点击引脚事件
svgRoot.on('mousedown',function(e){
if(1 == e.which){
// 编辑连线
var target = $(e.target).context
if (isEditPolyline) {
editPolyLine.polyline.stroke('#800')
editPolyLine = null;
isEditPolyline = false;
}
// 添加器件过程
if (!isAddCmpt && activeCmpt == null){
// 矩形选中
if (!isSelectBox && isComplatePath) {
svgComponent.unSelectAll()
isSelectBox = true
isMulSelect = false
isMoveMulSelect = false
svgmenu.disableOtherMenu()
selectRectBox.attr({'x':e.offsetX,'y':e.offsetY,'width':0,'height':0})
currentMousePointer.x = e.offsetX
currentMousePointer.y = e.offsetY
selectRectBox.show()
return;
}
// 添加连线点
if (!isComplatePath && currentPolyline != null ){
// 最终连接引脚
var points = currentPolyline.attr('points').split(' ')
var l = points.length
// 添加的点
var addP = points[l-2]
points.splice(l-2,0,addP)
currentPolyline.attr('points',points)
}
}else{
if (typeof(activeCmpt.addCallback) == 'function') {
activeCmpt.addCallback()
}
activeCmpt.index = svgComponent.cmpts.length
svgComponent.cmpts.push(activeCmpt)
isAddCmpt = false;
activeCmpt = null;
return;
}
}
if (!isComplatePath && currentPolyline != null && 3 == e.which){
var points = currentPolyline.attr('points').split(' ')
var l = points.length
// 仅剩起点
if (l <= 3) {
currentPolyline.remove()
currentPolylineObj.startCmpt.circuitMap.delete('startFoot_'+currentPolylineObj.startFoot.attr('id')+'_'+svgPolyLineNum)
svgComponent.finishLine(false)
return;
}
// 添加的点
points.splice(l-1,1)
currentPolyline.attr('points',points)
}
})
svgRoot.on('mouseup',function(e){
if(e.which == 1){
// 隐藏选中框
if(isSelectBox && !isMulSelect){
svgComponent.cmpts.forEach(function(cmpt){
cmpt.selectedJudge()
})
svgComponent.circuits.forEach(function(c){
c.selectedLine()
})
selectRectBox.hide()
isSelectBox = false
if (selectCmpts.length !=0 || selectPolylines.length != 0) {
isMulSelect = true // 打开多选
svgmenu.enableMenu()//启用菜单
}
return;
}
// 批量移动
if (isMulSelect && isMoveMulSelect) {
selectCmpts.forEach(function(cmpt){
var t = cmpt.group.transform()
var d = {}
d.x = changeGrid(t.e) - t.e
d.y = changeGrid(t.f) - t.f
// 调用连线调整方法
cmpt.circuitMap.forEach(function(v,k){
if(!v.isSelected){
if (k.split('_')[0] == 'startFoot') {
v.moveFootPolyline(1,d)
}else {
v.moveFootPolyline(2,d)
}
}
})
cmpt.group.move(changeGrid(t.e),changeGrid(t.f))
})
selectPolylines.forEach(function(l){
var t = l.group.transform()
var d = {}
d.x = t.e - changeGrid(t.e)
d.y = t.f - changeGrid(t.f)
l.group.move(changeGrid(t.e),changeGrid(t.f))
// 调用自身调整方法
if (!l.startCmpt.isSelected) {
l.moveFootPolyline(1,d)
}
if (!l.endCmpt.isSelected) {
l.moveFootPolyline(2,d)
}
})
svgRootGroup.attr('style','cursor:default')
return;
}
}else if (e.which == 2) {
svgRootGroup.attr('style','cursor:default')
}
})
$('#svgroot').on('mouseenter',function(e){
if (isAddCmpt && activeCmpt != null && activeCmpt.group == null) {
activeCmpt.component()
}
})
$('#svgroot').on('mouseleave',function(e){
if (isAddCmpt && activeCmpt != null) {
activeCmpt.group.remove()
activeCmpt.group = null
}
})
$('#box-workarea').on('mousewheel',function (e) {
e.preventDefault();
e.stopPropagation();
var target = $(e.target).context
var delta = e.originalEvent.wheelDelta
var scale = originScale;
originScale = originScale * 10
if(delta > 0 && originScale < 50)
originScale += 2
else if (delta < 0 && originScale > 2 && originScale <= 50)
originScale -= 2
originScale = originScale / 10
var t = svgRoot.transform();
svgRoot.scale(originScale,(e.offsetX - (t.e + svgRoot.node.clientWidth/2))/scale,(e.offsetY - (t.f + svgRoot.node.clientHeight/2))/scale)
if (originScale <= 0.6) {
gridRect.hide()
}else{
gridRect.show()
}
})
$('#svgroot').on('mousemove',function (e) {
if (e.which == 1) {
if (isSelectBox) {
var x = currentMousePointer.x
var y = currentMousePointer.y
var d = {}
d.x = Math.abs(x- e.offsetX)
d.y = Math.abs(y- e.offsetY)
if (x <= e.offsetX) {
selectRectBox.attr('x',x);
}else {
selectRectBox.attr('x',e.offsetX);
}
if (y <= e.offsetY) {
selectRectBox.attr('y',y);
}else {
selectRectBox.attr('y',e.offsetY);
}
selectRectBox.size(d.x,d.y)
}
if (isMulSelect && isMoveMulSelect) {
var d = {},td = {}
d.x = e.originalEvent.movementX/originScale
d.y = e.originalEvent.movementY/originScale
td.x = -d.x
td.y = -d.y
selectCmpts.forEach(function(cmpt){
if (!cmpt.isLock) {
cmpt.group.dmove(d.x,d.y)
// 调用连线调整方法
cmpt.circuitMap.forEach(function(v,k){
if(!v.isSelected){
if (k.split('_')[0] == 'startFoot') {
v.moveFootPolyline(1,d)
}else {
v.moveFootPolyline(2,d)
}
}
})
}
})
selectPolylines.forEach(function(l){
l.group.dmove(d.x,d.y)
// 调用自身调整方法
if (!l.startCmpt.isSelected) {
l.moveFootPolyline(1,td)
}
if (!l.endCmpt.isSelected) {
l.moveFootPolyline(2,td)
}
})
svgRootGroup.attr('style','cursor:move')
return;
}
}
// 鼠标中键全部器件拖动
if (e.which == 2) {
var t = svgRoot.transform()
t.e = t.e+e.originalEvent.movementX
t.f = t.f+e.originalEvent.movementY
svgRoot.transform(t)
svgRootGroup.attr('style','cursor:move')
return;
}
// 添加器件中
if (isAddCmpt && activeCmpt != null && activeCmpt.group != null) {
activeCmpt.svgCmptMove(changeGrid(e.offsetX - activeCmpt.group.attr('width')/2),changeGrid(e.offsetY - activeCmpt.group.attr('height')/2))
}
// 绘制连线中
if (!isComplatePath && currentPolyline != null && !isAddCmpt){
var transform = currentFootTransform
var x = changeGrid(e.offsetX) ,y = changeGrid(e.offsetY) ;
var points = currentPolyline.attr('points').split(' ')
var endP = null;
var preP = null;
var nearP = null;
if(points.length>=3){
endP = points.pop().split(',')
nearP = points.pop().split(',')
preP = points[points.length - 1].split(',')
}else {
endP = points.pop().split(',')
preP = points[points.length - 1].split(',')
nearP = preP
}
// 终点与第三个点比较
if (Math.abs(preP[0] - x)<5 && !changeLineX){
changeLineX = true;
changeLineY = false;
}
if (Math.abs(preP[1] - y)<5 && !changeLineY){
changeLineX = false;
changeLineY = true;
}
if(changeLineX && !changeLineY){
nearP[0] = preP[0]
nearP[1] = y
}else {
nearP[0] = x
nearP[1] = preP[1]
}
points.push(nearP.toString())
points.push(x+','+y)
currentPolyline.attr('points',points)
crossLine_X.plot('M'+x+' 0 v'+$('#svgroot').height())
crossLine_Y.plot('M0 '+y+' h'+$('#svgroot').width())
}
})
// 右键菜单对象
function menu(){
let _this = this
// 菜单 DOM元素
let menu = $('#svgmenu')
// 删除按钮 DOM元素
this.delBtnEl = $('#delCmpts')[0];
// 锁定按钮 DOM元素
this.lockBtnEl = $('#lockCmpts')[0];
// 解锁按钮 DOM元素
this.unLockBtnEl = $('#unLockCmpts')[0];
// 引脚按钮 DOM元素
this.viewFootEl = $('#viewFoot')[0];
// 全部引脚按钮 DOM元素
this.viewAllFootEl = $('#viewAllFoot')[0];
// 启用菜单
this.enableMenu = function(){
_this.enableMenu(_this.delBtnEl)
_this.enableMenu(_this.lockBtnEl)
_this.enableMenu(_this.unLockBtnEl)
}
// 禁用菜单
this.disableOtherMenu = function(){
_this.disableMenu(_this.delBtnEl)
_this.disableMenu(_this.lockBtnEl)
_this.disableMenu(_this.unLockBtnEl)
_this.hideMenu(_this.viewFootEl)
}
// 单个器件
this.selectCmptMenu = function(cmpt){
if (cmpt.isLock) {
_this.disableMenu(_this.delBtnEl)
_this.disableMenu(_this.lockBtnEl)
_this.enableMenu(_this.unLockBtnEl)
}else {
_this.enableMenu(_this.delBtnEl)
_this.enableMenu(_this.lockBtnEl)
_this.disableMenu(_this.unLockBtnEl)
}
_this.showMenu(_this.viewFootEl)
if (!cmpt.isDisplayFootText) {
menu.menu('setText', {target: _this.viewFootEl,text: '显示引脚'});
}else {
menu.menu('setText', {target: _this.viewFootEl,text: '隐藏引脚'});
}
}
// 删除器件
this.delCmpts = function(){
removeSelect()
}
// 锁定器件
this.lockCmpts = function(){
selectCmpts.forEach(function(cmpt){
cmpt.unSelected()
cmpt.isLock = true;
})
selectPolylines.forEach(function(l){
})
selectCmpts = []
selectPolylines = []
}
// 解锁器件
this.unLockCmpts = function(){
selectCmpts.forEach(function(cmpt){
cmpt.unSelected()
cmpt.isLock = false;
})
selectPolylines.forEach(function(l){
})
selectCmpts = []
selectPolylines = []
}
// 合并器件
this.addGroup = function(){
}
// 分解器件
this.unGroup = function(){
}
// 引脚显示
this.viewFoot = function(){
selectCmpts.forEach(function(cmpt){
cmpt.viewFoot()
})
}
// 显示全部引脚
this.viewAllFoot = function(){
var item = menu.menu('getItem', _this.viewAllFootEl);
if (item.text == '显示全部引脚') {
menu.menu('setText', {target: _this.viewAllFootEl,text: '隐藏引脚'});
svgComponent.cmpts.forEach(function(cmpt){
if (!cmpt.isDisplayFootText) {
cmpt.viewFoot()
}
})
}else{
menu.menu('setText', {target: _this.viewAllFootEl,text: '显示引脚'});
svgComponent.cmpts.forEach(function(cmpt){
if (cmpt.isDisplayFootText) {
cmpt.viewFoot()
}
})
}
}
// 放大或缩小
this.zoomChange = function(type){
var scale = originScale
originScale = originScale * 10
switch (type) {
// 缩小
case 'shrink':
if (originScale > 2 && originScale <= 50)
originScale -= 2
break;
// 放大
case 'magnify':
if(originScale < 50)
originScale += 2
break;
}
originScale = originScale / 10
var t = svgRoot.transform();
svgRoot.scale(originScale,(currentMousePointer.x - (t.e + svgRoot.node.clientWidth/2))/scale,(currentMousePointer.y - (t.f + svgRoot.node.clientHeight/2))/scale)
if (originScale <= 0.6) {
gridRect.hide()
}else{
gridRect.show()
}
}
// 菜单禁用
this.disableMenu = function(el){
menu.menu('disableItem',el)
}
// 菜单启用
this.enableMenu = function(el){
menu.menu('enableItem',el)
}
// 隐藏菜单
this.hideMenu = function(el){
menu.menu('hideItem',el)
}
// 显示菜单
this.showMenu = function(el){
menu.menu('showItem',el)
}
}
// 菜单处理
function menuHandler(obj){
var type = obj.name
switch (type) {
// 缩小
case 'shrink':
// 放大
case 'magnify':
svgmenu.zoomChange(type)
break;
// 删除
case 'delete':
svgmenu.delCmpts()
break;
// 锁定
case 'lock':
svgmenu.lockCmpts()
break;
// 解锁
case 'unlock':
svgmenu.unLockCmpts()
break;
// // 合并
// case 'combine':
// svgmenu.combineCmpts()
// break;
// // 分解
// case 'decompose':
// svgmenu.decompose()
// break;
case 'viewFoot':
svgmenu.viewFoot();
break;
case 'viewAllFoot':
svgmenu.viewAllFoot();
break;
case 'viewProperty':
pubMessage('【属性】功能正在开发中...');
break;
}
}
function SvgCmpt(){
let _this = this;
// 器件id
this.id='';
// 器件类型 0 —— 普通器件,1 —— vss,2 —— 输入,输出 ,3 —— 电阻、电容、电感
this.cmptType = 0;
// 输入、输出对象
this.instr = null;
// 模块id
this.moduleId = '';
// 模块位置
this.modulePos = '';
// 模块在集合中的位置
this.index = 0;
// 显示名称
this.displayName='';
// 显示值
this.displayValue='';
// 器件左上角坐标
this.location='';
// 最近移动点x坐标
this.laster_X=0;
// 最近移动点y坐标
this.laster_y=0;
// 器件线宽
this.stroke ='';
// 器件颜色
this.strokeColor = '';
// 器件引脚集合
this.foots = [];
// 旋转角度 90,180,270
this.angle = 0;
// 器件描述内容
this.cmptContent = '';
// 器件所在组
this.group = null;
// clone对象
this.cloneGroup = null;
// 引脚文字对象
this.footTextGroup = null;
// 添加器件回调函数
this.addCallback = null;
// 删除器件回调函数
this.delCallback = null;
// 器件面积
this.size = {};
// 器件状态(是否锁定)
this.isLock = false;
// 是否合并
this.isCombine = false;
// 合并后的父group
this.parentGroup = null;
// 器件是否选中
this.isSelected = false;
// 器件外边框
this.outRect = null
// 器件引脚预连线
this.isPreLine = false;
// 器件是否在移动
this.isMoving = false;
// 是否被移除
this.isDelFlag = false;
// 是否显示引脚名称
this.isDisplayFootText = false;
// VCC VEE GND
this.isOpenVCC = false;
this.isOpenVEE = false;
this.isOpenGND = false;
// 器件上面的连线集合
this.circuitMap = new Map;
// 器件resize 放大缩小
this.svgCmptResize = function(size){
// 放大或缩小group
}
// 移动器件
this.svgCmptMove = function(offsetX,offsetY){
// 移动group
if(_this.group!=null)
_this.group.move(offsetX,offsetY)
}
// 选中绘制样式
this.drawTracker = function () {
//初始化点击事件
}
// 旋转图形
this.rotateCmpt = function(){
_this.angle += 90
_this.group.rotate(_this.angle)
}
// 取消选中
this.unSelected = function(){
if (_this.isSelected) {
_this.isSelected = false
_this.outRect.hide()
}
}
// 判断是否选中
this.selectedJudge = function () {
var t = _this.group.transform()
var x = t.e + _this.size.width/2
var y = t.f + _this.size.height/2
if (selectRectBox.inside(x,y)) {
selectCmpts.push(_this)
_this.isSelected = true
_this.outRect.show()
}
}
// 删除器件
this.remove = function(){
if (!_this.isLock) {
_this.group.remove()
// 删除连线
_this.circuitMap.forEach(function(v,k){
var data = v.polyline.attr('id')
var req = new ReqToSystem(214,data)
req.response=function(resp){
if(resp!=null){
v.removePolyline();
}else{
pubMessage('删除连线失败!','error');
}};
if (!v.isDeleted){
send(req);
}
})
}
}
this.viewFoot = function (){
// 是否显示引脚名称
if (_this.isDisplayFootText) {
_this.isDisplayFootText = false
_this.footTextGroup.hide()
}else{
_this.isDisplayFootText = true
_this.footTextGroup.show()
}
}
this.component = function(){
//创建器件组
var group = svgRootGroup.group().size(_this.size.width,_this.size.height).attr({x:20,y:20})
var cmptGroup = group.group().id('svgcmpt_'+_this.id).size(_this.size.width,_this.size.height).attr({x:20,y:20})
var outRect = group.rect().size(_this.size.width,_this.size.height).fill('#ffffff00').stroke({color:'#f96a6a8f',width:'1'})
group.add(outRect)
_this.outRect = outRect;
outRect.hide()
//添加器件图形
var list = cmptGroup.svg(this.cmptContent)
//显示器件值或器件名称
if(_this.cmptType == 3){
$('#displayeName'+_this.id).text(_this.displayName)
$('#displayValue'+_this.id).text(_this.displayValue)
}
// 添加器件引脚
var footgroups = group.group().id('foot')
var footTextGroups = group.group().id('textFoot')
var footTextStr = ''
this.foots.forEach(function (v) {
var pos = 0
if (_this.modulePos <= 16) {
pos = Number(v.index) + _this.modulePos * 16
footTextStr = _this.modulePos + '-' + (Number(v.index))
}else if(_this.modulePos>192 && _this.modulePos <= 203){
pos = _this.modulePos + Number(v.index)
footTextStr = parseInt(_this.modulePos/16) + '-' + (Number(v.index)+1)
}
var cx = v.x
var cy = v.y
// 引脚文字
var tx = v.x
var ty = v.y
var text = svgRoot.text(footTextStr).font({x:tx,y:ty,family:'Times New Roman',size:5}).fill('green')
footTextGroups.add(text)
var circle = svgRoot.circle().attr({
cx:cx,cy:cy,r:5,stroke:'#ffffff00',fill:'#ffffff00',id:'foot_'+pos
}).stroke({width:1})
circle.mouseenter(function (e) {
e.preventDefault()
$(e.target).attr('fill','red')
// 处于欲连线状态
if (e.which == 0 && isComplatePath && currentPolyline == null && !isMulSelect) {
_this.isPreLine = true
}
if (e.which == 0 && _this.isSelected && !isMulSelect) {
selectCmpt = null
_this.isSelected = false
_this.outRect.hide()
}
})
circle.mouseleave(function (e) {
$(e.target).attr('fill','#ffffff00')
// 关闭欲连线状态
if (e.which == 0) {
_this.isPreLine = false
}
})
circle.mouseup(function (e) {
e.preventDefault()
if(isAddCmpt && activeCmpt !=null){
isAddCmpt = false;
activeCmpt = null;
return;
}
_this.isPreLine = false
//完成连线
if (!isComplatePath && currentPolyline != null && !isMulSelect){
var points = currentPolyline.attr('points').split(' ')
points.pop(); // 删除末点
var nearP = points[points.length-1].split(',')
points.pop();// 删除邻近点
// 偏移坐标
var t = circle.parent().parent().transform()
// 绝对坐标
var x = circle.attr('cx') + t.e , y =circle.attr('cy') + t.f;
if (changeLineX) {
nearP[1] = y
}
if (changeLineY) {
nearP[0] = x
}
points.push(nearP.join(','))
points.push(x+','+y)
// 发送验证连线请求,若连线无效则返回
// 添加末点引脚连线,先本地检查,后网络检查
currentPolylineObj.endPos = circle.attr('id').split('_')[1]
if(!checkPolyLine(currentPolylineObj.startPos,currentPolylineObj.endPos)){
// 无效连线,并删除连线
currentPolyline.remove()
pubMessage('无效连线!','error');
currentPolylineObj.startCmpt.circuitMap.delete('startFoot_'+currentPolylineObj.startFoot.attr('id')+'_'+svgPolyLineNum)
svgComponent.finishLine(false)
return ;
}
var data = currentPolylineObj.polylinePosResult()
var req = new ReqToSystem(213,data)
req.response=function(resp){
if(resp!=null){
// svg连线对象
currentPolyline.attr('points',points)
currentPolyline.attr('id',data)
currentPolylineObj.polyline = currentPolyline
currentPolylineObj.points = points
currentPolylineObj.endFoot = circle
currentPolylineObj.endCmpt = _this
currentPolylineObj.index = svgPolyLineNum
svgComponent.addCircuit(currentPolylineObj)
_this.circuitMap.set('endFoot_'+circle.attr('id')+'_'+svgPolyLineNum,currentPolylineObj)
svgPolyLineNum++;
svgComponent.finishLine(true);
}else{
pubMessage('连线失败!','error');
}
}
send(req);
return;
}
// 开启连线
svgComponent.createRootPath(e,circle,_this)
// 添加起点连线
_this.circuitMap.set('startFoot_'+circle.attr('id')+'_'+svgPolyLineNum,currentPolylineObj)
})
footgroups.add(circle)
})
group.add(footgroups)
group.on('mousedown',function (e) {
if (e.which == 1) {
if(isAddCmpt && activeCmpt !=null){
if (typeof(activeCmpt.addCallback) == 'function') {
activeCmpt.addCallback()
}
svgComponent.cmpts.push(activeCmpt)
isAddCmpt = false;
activeCmpt = null;
return;
}else if(isMulSelect && !isMoveMulSelect){
isMoveMulSelect = true
}
}
})
// 鼠标悬浮在器件上
group.on('mouseover',function(e){
if (isComplatePath && !_this.isSelected && !_this.isMoving && !isAddCmpt && !_this.isPreLine && !isSelectBox && !isMulSelect) {
selectCmpt = _this
_this.isSelected = true
outRect.show()
}
})
// 鼠标离开器件
group.on('mouseleave',function(e){
if(!isSelectBox && selectCmpt != null && !isMulSelect){
selectCmpt = null
_this.isSelected = false
outRect.hide()
}
})
// 双击事件
if (_this.cmptType == 2) {
group.on('dblclick',function(){
if(!instrument)
instrument=new Instrument();
if(_this.id=='DS')
instrument.ds.open(_this.instr);
else if(_this.id=='DG')
instrument.dg.open(_this.instr);
});
}
group.draggable().on('beforedrag',e =>{
if (!_this.isMoving && !_this.isPreLine && !isMulSelect && !_this.isLock && !isAddCmpt) {
var d = e.detail
var t = _this.group.transform()
_this.laster_X = changeGrid(t.x)
_this.laster_Y = changeGrid(t.y)
_this.group.attr('style','cursor:move')
}
}).on('dragmove',e =>{
e.preventDefault()
var d = e.detail
if (!_this.isLock && !_this.isMoving && d.event.type == 'mousemove' && isComplatePath && !_this.isPreLine && !isMulSelect) {
_this.isMoving = true;
_this.cloneGroup = group.clone();
_this.cloneGroup.opacity(0.5)
_this.cloneGroup.attr('style','cursor:move')
}else if(!_this.isLock && d.event.type == 'mousemove'&& isComplatePath && !_this.isPreLine && !isMulSelect){
_this.cloneGroup.dmove(d.event.movementX/originScale,d.event.movementY/originScale)
//_this.cloneGroup.move(d.event.offsetX - _this.cloneGroup.attr('width')/2,d.event.offsetY-_this.cloneGroup.attr('height')/2)
}
}).on('dragend',e =>{
if (!_this.isLock && _this.isMoving && !_this.isPreLine && !isMulSelect) {
var detail = e.detail
var group = _this.group;
var movement = {};
var d = {}
var ct = _this.cloneGroup.transform()
var t = group.transform()
t.e = changeGrid(ct.x)
t.f = changeGrid(ct.y)
group.transform(t)
d.x = changeGrid(ct.x) - _this.laster_X
d.y = changeGrid(ct.y) - _this.laster_Y
_this.cloneGroup.remove()
_this.isMoving = false;
_this.circuitMap.forEach(function(v,k){
if (k.split('_')[0] == 'startFoot') {
v.moveFootPolyline(1,d)
}else {
v.moveFootPolyline(2,d)
}
})
}
_this.group.attr('style','cursor:defalut')
})
// 是否显示引脚名称
if (!_this.isDisplayFootText) {
footTextGroups.hide()
_this.footTextGroup = footTextGroups
}
this.group = group;
}
}
//删除选中器件、连线
function removeSelect(){
if (selectCmpts.length>0) {
selectCmpts.forEach(function(cmpt){
if (cmpt != null && !cmpt.isLock) {
if (typeof(cmpt.delCallback) == 'function') {
cmpt.delCallback()
}
cmpt.remove();
}
})
selectCmpts = []
}else if (selectCmpt != null && !selectCmpt.isLock) {
if (typeof(selectCmpt.delCallback) == 'function') {
selectCmpt.delCallback()
}
selectCmpt.remove();
// 删除器件
//svgComponent.removeCmpt()
}
// 删除连线
if (selectPolylines.length>0) {
selectPolylines.forEach(function(line){
var data = line.polyline.attr('id')
var req = new ReqToSystem(214,data)
req.response=function(resp){
if(resp!=null){
line.removePolyline();
}else{
pubMessage('删除连线失败!','error');
}};
if (!line.isDeleted) {
send(req);
}
})
selectPolylines = [];
}
if(editPolyLine != null){
var data = editPolyLine.polyline.attr('id')
var req = new ReqToSystem(214,data)
req.response=function(resp){
if(resp!=null){
editPolyLine.removePolyline();
editPolyLine = null;
isEditPolyline = false;
}else{
pubMessage('删除连线失败!','error');
}};
if (!editPolyLine.isDeleted) {
send(req);
}
}
isMulSelect = false;
isMoveMulSelect = false;
}
function SvgCircuit(){
let _this = this;
// index序列
this.index = 0;
// groupId
this.groupId = '';
// group属性
this.group = null;
// 连线对象
this.polyline = null
// 连线起点引脚对象
this.startFoot = null;
// 连线终点引脚对象
this.endFoot = null;
// 连线颜色
this.strokeColor = '';
// 连线起点在大节点位置
this.startPos = '';
// 连线终点在大节点位置
this.endPos = '';
// 连线起点器件对象
this.startCmpt ='';
// 连线末点器件对象
this.endCmpt = '';
// 连线点集合
this.points = [];
// 是否被选中
this.isSelected = false;
// 是否已经被删除
this.isDeleted = false;
// 移动器件时更改连线 传入引脚参数 1-起点 2-终点
this.moveFootPolyline=function(type,movement){
if (!isComplatePath && _this.endFoot == null) {
return;
}
var l = _this.points.length
if (l > 4 ) {
_this.points = svgComponent.optimizePolyline(_this.points)
}
if (l>=3) {
switch (type) {
case 1:
var sp = _this.points[0].split(',')
var np = _this.points[1].split(',')
var tp = _this.points[2].split(',')
_this.points.splice(0,1,(Number(sp[0])+movement.x)+','+(Number(sp[1])+movement.y))
if(sp[0] == np[0] && sp[1] != np[1]){
_this.points.splice(1,1,(Number(np[0])+movement.x)+','+np[1])
}else if(sp[0] != np[0] && sp[1] == np[1]){
_this.points.splice(1,1,np[0]+','+(Number(np[1])+movement.y))
}
if (tp[0] == np[0]) {
_this.points.splice(1,1,tp[0]+','+(Number(sp[1])+movement.y))
}else if (tp[1] == np[1]){
_this.points.splice(1,1,(Number(sp[0])+movement.x)+','+tp[1])
}else {
if (Math.abs((Number(sp[0])+movement.x)-tp[0])>Math.abs((Number(sp[1])+movement.y)-tp[1])) {
_this.points.splice(1,1,tp[0]+','+(Number(sp[1])+movement.y))
}else {
_this.points.splice(1,1,(Number(sp[0])+movement.x)+','+tp[1])
}
}
_this.polyline.attr('points',_this.points)
break;
case 2:
var ep = _this.points[l-1].split(',')
var np = _this.points[l-2].split(',')
var tp = _this.points[l-3].split(',')
_this.points.splice(l-1,1,(Number(ep[0])+movement.x)+','+(Number(ep[1])+movement.y))
if (ep[0] == np[0] && ep[1] != np[1]) {
_this.points.splice(l-2,1,(Number(np[0])+movement.x)+','+np[1])
}else if(ep[0] != np[0] && ep[1] == np[1]){
_this.points.splice(l-2,1,np[0]+','+(Number(np[1])+movement.y))
}
if (tp[0] == np[0]) {
_this.points.splice(l-2,1,tp[0]+','+(Number(ep[1])+movement.y))
}else if (tp[1] == np[1]){
_this.points.splice(l-2,1,(Number(ep[0])+movement.x)+','+tp[1])
}else {
if (Math.abs((Number(ep[0])+movement.x)-tp[0])>Math.abs((Number(ep[1])+movement.y)-tp[1])) {
_this.points.splice(l-2,1,tp[0]+','+(Number(ep[1])+movement.y))
}else {
_this.points.splice(l-2,1,(Number(ep[0])+movement.x)+','+tp[1])
}
}
_this.polyline.attr('points',_this.points)
break;
}
}
}
this.polylinePosResult = function() {
if (_this.startPos != '' && _this.endPos != '') {
return _this.startPos +',' + _this.endPos
}else {
return '';
}
}
// 移除连线
this.removePolyline=function(){
if (!_this.isDeleted) {
// 删除线段
_this.isDeleted = true;
_this.group.remove();
// 移除起点和末点
_this.startCmpt.circuitMap.delete('startFoot_'+_this.startFoot.attr('id')+'_'+_this.index)
_this.endCmpt.circuitMap.delete('endFoot_'+_this.endFoot.attr('id')+'_'+_this.index)
//执行删除连线回调
$('#sendState').show();
}
}
// 选中连线逻辑
this.selectedLine=function(){
var flag = 0;
var points = _this.polyline.attr('points').split(' ')
var t = _this.group.transform()
points.forEach(function(pt){
var p = pt.split(',')
if (selectRectBox.inside(Number(p[0])+t.e,Number(p[1])+t.f)){
flag++
}else {
flag--
}
})
if (flag >= points.length - 1) {
selectPolylines.push(_this)
_this.isSelected = true
_this.polyline.stroke('#ff0000')
}
}
// 取消选中
this.unSelected=function(){
_this.isSelected = false;
_this.polyline.stroke('#800')
}
}
function SvgComponent(){
let _this =this
// 初始化svg对象
this.svgroot = svgRoot
// 基本器件类型
this.basicCmpt = ['电阻','电容','电感']
//存放器件
this.cmpts=[];
//电路连线
this.circuits=[];
//画图方法
this.draw=function(svgCmpt){
svgCmpt.component()
}
// 取消全部选中器件
this.unSelectAll = function(){
selectCmpts.forEach(function(cmpt){
cmpt.unSelected()
})
selectPolylines.forEach(function(circuit){
circuit.unSelected()
})
selectCmpts = []
selectPolylines = []
}
//添加器件
this.addCmpt=function(cmpt){
// 初始化器件
svgCmpt = new SvgCmpt
svgCmpt.id = cmpt.id
svgCmpt.moduleId = cmpt.moduleId
svgCmpt.displayName = cmpt.displayName
svgCmpt.isOpenVCC = cmpt.openVcc >0?true:false;
svgCmpt.isOpenVEE = cmpt.openVee >0?true:false;
svgCmpt.isOpenGND = cmpt.openGnd >0?true:false;
svgCmpt.modulePos = cmpt.pos
var footContent = cmpt.cmptSvg.footContent.split('</circle>')
var foots = []
JSON.parse(cmpt.foots).forEach(function(v,i){
var foot = {}
var el = new DOMParser().parseFromString(footContent[i]+'</circle>','text/html').body.childNodes[0]
foot['id'] = "node_"+v.node +"_foot_"+v.foot;
foot['index'] = v.node
foot['pos'] = v.foot
foot['x'] = el.getAttribute('cx');
foot['y'] = el.getAttribute('cy');
foots.push(foot)
})
// svgCmpt.cmptContent = '<path d="M 10 10 h -10" fill="none" stroke="#000fff" stroke-width="1" id="gge1201"></path>,' +
// '<path d="M 10 20 h -10" fill="none" stroke="#000fff" stroke-width="1" id="gge1202"></path>,' +
// '<path d="M 10 30 h -10" fill="none" stroke="#000fff" stroke-width="1" id="gge1203"></path>,' +
// '<path d="M 10 40 h -10" fill="none" stroke="#000fff" stroke-width="1" id="gge1204"></path>,' +
// '<path d="M 10 50 h -10" fill="none" stroke="#000fff" stroke-width="1" id="gge1205"></path>,' +
// '<path d="M 10 60 h -10" fill="none" stroke="#000fff" stroke-width="1" id="gge1206"></path>,' +
// '<path d="M 10 70 h -10" fill="none" stroke="#000fff" stroke-width="1" id="gge1207"></path>,' +
// '<path d="M 10 80 h -10" fill="none" stroke="#000fff" stroke-width="1" id="gge1208"></path>,' +
// '<rect id="gge1189" locked="0" c_etype="" x="10" y="0" width="80" height="100" stroke="#000fff" stroke-width="1" fill="#ffffff00" c_shapetype="line"></rect>,' +
// '<path d="M 90 10 h 10" fill="none" stroke="#000fff" stroke-width="1" id="gge1195"></path>,'+
// '<path d="M 90 20 h 10" fill="none" stroke="#000fff" stroke-width="1" id="gge1196"></path>,'+
// '<path d="M 90 30 h 10" fill="none" stroke="#000fff" stroke-width="1" id="gge1197"></path>,'+
// '<path d="M 90 40 h 10" fill="none" stroke="#000fff" stroke-width="1" id="gge1198"></path>,'+
// '<path d="M 90 50 h 10" fill="none" stroke="#000fff" stroke-width="1" id="gge1199"></path>,'+
// '<path d="M 90 60 h 10" fill="none" stroke="#000fff" stroke-width="1" id="gge1200"></path>,'+
// '<path d="M 90 70 h 10" fill="none" stroke="#000fff" stroke-width="1" id="gge1194"></path>,'+
// '<path d="M 90 80 h 10" fill="none" stroke="#000fff" stroke-width="1" id="gge1201"></path>'
var svgContent = cmpt.cmptSvg.svgContent
if($.inArray(cmpt.cmptItem.itemName,_this.basicCmpt) != -1){
svgCmpt.cmptType = 3
svgCmpt.displayValue = cmpt.proval+cmpt.unit
svgContent = svgContent.replace('"displayName"','"displayeName'+svgCmpt.id+'"').replace('displayValue','displayValue'+svgCmpt.id)
}
svgCmpt.cmptContent = svgContent //'<rect x="10" y="10" width="300" height="300" fill="#ffffff00" stroke="#000fff" stroke-width="1"></rect><rect x="150" y="50" width="100" height="200" fill="#ffffff00" stroke="#000fff" stroke-width="1"></rect><path d="M 0 100 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 0 120 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 0 140 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 0 160 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 0 200 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 0 220 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 10 100 h130" fill="none" stroke="#e3c8c8" stroke-width="1"></path><path d="M 10 120 h130" fill="none" stroke="#e3c8c8" stroke-width="1"></path><path d="M 10 140 h130" fill="none" stroke="#e3c8c8" stroke-width="1"></path><path d="M 10 160 h130" fill="none" stroke="#e3c8c8" stroke-width="1"></path><path d="M 140 80 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 140 100 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 140 120 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 140 140 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 140 160 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 70 220 v10" stroke="#000fff" stroke-width="1"></path><path d="M 60 230 h20" stroke="#000fff" stroke-width="1"></path><path d="M 60 240 h20" stroke="#000fff" stroke-width="1"></path><path d="M 70 240 v10" stroke="#000fff" stroke-width="1"></path><path d="M 200 260 v-10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 200 260 v50" fill="none" stroke="#e3c8c8" stroke-width="1"></path><path d="M 200 320 v-10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 250 130 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 260 130 h50" fill="none" stroke="#e3c8c8" stroke-width="1"></path><path d="M 310 130 h10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 40 240 v10" stroke="#000fff" stroke-width="1"></path><path d="M 30 250 h20" stroke="#000fff" stroke-width="1"></path><path d="M 30 260 h20" stroke="#000fff" stroke-width="1"></path><path d="M 40 260 v10" stroke="#000fff" stroke-width="1"></path><path d="M 200 10 v-10" fill="none" stroke="#000fff" stroke-width="1"></path><path d="M 200 10 v40" fill="none" stroke="#e3c8c8" stroke-width="1"></path><path d="M 200 50 v-10" fill="none" stroke="#000fff" stroke-width="1"></path><polyline points="140,80 100,80 100,30 200,30" fill="none" stroke="#e3c8c8" stroke-width="1"></polyline><polyline points="10,200 70,200 70,220" fill="none" stroke="#e3c8c8" stroke-width="1"></polyline><polyline points="10,220 40,220 40,240" fill="none" stroke="#e3c8c8" stroke-width="1"></polyline><polyline points="40,270 40,280 200,280" fill="none" stroke="#e3c8c8" stroke-width="1"></polyline><polyline points="70,240 70,280" fill="none" stroke="#e3c8c8" stroke-width="1"></polyline>'
//+'<text id="foot_name" x="20" y="100" font-family="Times New Roman" font-size="9pt" fill="#000fff">DIS</text><text id="foot_name" x="20" y="120" font-family="Times New Roman" font-size="9pt" fill="#000fff">TH</text><text id="foot_name" x="20" y="140" font-family="Times New Roman" font-size="9pt" fill="#000fff">TR</text><text id="foot_name" x="20" y="160" font-family="Times New Roman" font-size="9pt" fill="#000fff">CV</text><text id="foot_name" x="20" y="200" font-family="Times New Roman" font-size="9pt" fill="#000fff">7</text><text id="foot_name" x="20" y="220" font-family="Times New Roman" font-size="9pt" fill="#000fff">5</text><text id="foot_name" x="155" y="80" font-family="Times New Roman" font-size="9pt" fill="#000fff">RST</text><text id="foot_name" x="155" y="100" font-family="Times New Roman" font-size="9pt" fill="#000fff">DIS</text><text id="foot_name" x="155" y="120" font-family="Times New Roman" font-size="9pt" fill="#000fff">THR</text><text id="foot_name" x="155" y="140" font-family="Times New Roman" font-size="9pt" fill="#000fff">TRI</text><text id="foot_name" x="155" y="160" font-family="Times New Roman" font-size="9pt" fill="#000fff">CON</text><text id="foot_name" x="220" y="130" font-family="Times New Roman" font-size="9pt" fill="#000fff">OUT</text><text id="foot_name" x="290" y="130" font-family="Times New Roman" font-size="9pt" fill="#000fff">VO</text><text id="foot_name" x="190" y="245" font-family="Times New Roman" font-size="9pt"fill="#000fff">GND</text><text id="foot_name" x="205" y="305" font-family="Times New Roman" font-size="9pt"fill="#000fff">GND</text><text id="foot_name" x="50" y="250" font-family="Times New Roman" font-size="6pt"fill="#000fff">C29</text><text id="C29_value" x="50" y="260" font-family="Times New Roman" font-size="6pt"fill="#000fff">0.1uF</text><text id="foot_name" x="80" y="230" font-family="Times New Roman" font-size="6pt"fill="#000fff">C30</text><text id="C30_value" x="80" y="240" font-family="Times New Roman" font-size="6pt"fill="#000fff">0.01uF</text><text id="foot_name" x="205" y="25" font-family="Times New Roman" font-size="9pt"fill="#000fff">VCC</text>'
svgCmpt.foots = foots // ['0,100','0,120','0,140','0,160','0,200','0,220','200,320','320,130','200,0']
svgCmpt.drawTracker()
var size = cmpt.cmptSvg.svgSize.split(',')
svgCmpt.size.width = size[0]
svgCmpt.size.height = size[1]
isAddCmpt = true; // 开启添加器件
if (typeof(cmpt.addCallback) == 'function') {
svgCmpt.addCallback = function(){
cmpt.addCallback()
}
}
if (typeof(cmpt.delCallback) == 'function') {
svgCmpt.delCallback = function(){
cmpt.delCallback()
}
}
activeCmpt = svgCmpt;
}
this.addVss = function(type,text,callback){
svgCmpt = new SvgCmpt
svgCmpt.size.width = 60
svgCmpt.size.height = 50
svgCmpt.cmptType = 1
svgCmpt.id = type
switch (type) {
case 'VCC':
svgCmpt.cmptContent = '<rect id="ggrect_gnd" x="0" y="0" width="60" height="50" stroke="#ffffff00" stroke-width="1" fill="#ffffff00"></rect>'+
'<text x="15" y="5" font-family="Times New Roman" font-size="9pt" fill="#000fff" id="gge1257">+5V</text>'+
'<path d="M 5 10 h 50" fill="none" stroke="#000fff" stroke-width="1" id="gge1259"></path>' +
'<path d="M 30 10 v 40" fill="none" stroke="#000fff" stroke-width="1" id="gge1258"></path>'
svgCmpt.foots = [{
id: "node_201_foot_vcc",index:0,pos:201,x:30,y:50
}]
svgCmpt.modulePos = 201
break;
case 'VEE':
svgCmpt.cmptContent = '<rect id="ggrect_gnd" x="0" y="0" width="60" height="50" stroke="#ffffff00" stroke-width="1" fill="#ffffff00"></rect>'+
'<text x="15" y="5" font-family="Times New Roman" font-size="9pt" fill="#000fff" id="gge1287">-5V</text>'+
'<path d="M 5 10 h 50" fill="none" stroke="#000fff" stroke-width="1" id="gge1289"></path>' +
'<path d="M 30 10 v 40" fill="none" stroke="#000fff" stroke-width="1" id="gge1299"></path>'
svgCmpt.foots = [{
id: "node_202_foot_vee",index:0,pos:202,x:30,y:50
}]
svgCmpt.modulePos = 202
break;
case 'GND':
svgCmpt.cmptContent = '<rect id="ggrect_gnd" x="0" y="0" width="60" height="60" stroke="#ffffff00" stroke-width="1" fill="#ffffff00"></rect>'+
'<path d="M 30 0 v 30" fill="none" stroke="#000fff" stroke-width="1" id="gge1268"></path>' +
'<path d="M 5 30 h 50" fill="none" stroke="#000fff" stroke-width="1" id="gge1269"></path>'+
'<path d="M 15 40 h 30" fill="none" stroke="#000fff" stroke-width="1" id="gge1270"></path>'+
'<path d="M 20 50 h 20" fill="none" stroke="#000fff" stroke-width="1" id="gge1271"></path>'
svgCmpt.foots = [{
id: "node_203_foot_gnd",index:0,pos:203,x:30,y:0
}]
svgCmpt.modulePos = 203
break;
}
isAddCmpt = true; // 开启添加器件
if (typeof(callback) == 'function') {
svgCmpt.addCallback = function(){
callback()
}
}
if (typeof(callback) == 'function') {
svgCmpt.delCallback = function(){
callback()
}
}
activeCmpt = svgCmpt;
}
// 添加仪器
this.addInstr = function(instr){
svgCmpt = new SvgCmpt
svgCmpt.id = instr.type
svgCmpt.instr = instr
var x = 25
switch (instr.name) {
case '示波器':
case '信号源':
x = 10;
break;
}
svgCmpt.cmptContent = '<rect id="ggrect_in" x="0" y="0" width="100" height="100" stroke="#ffffff00" stroke-width="1" fill="#ffffff00"></rect>'+
'<rect id="ggrect_1" x="2" y="2" width="96" height="76" stroke="#000fff" stroke-width="1" fill="#ffffff00" ></rect>'+
'<text id="ggtext_in" x="'+x+'" y="40" font-family="Times New Roman" font-size="20pt" fill="#000fff" >'+instr.name+'</text>'+
'<path d="M 20 60 v 40" fill="none" stroke="#000fff" stroke-width="1" id="ggpath_1"></path>'+
'<path d="M 40 60 v 40" fill="none" stroke="#000fff" stroke-width="1" id="ggpath_2"></path>'+
'<path d="M 60 60 v 40" fill="none" stroke="#000fff" stroke-width="1" id="ggpath_3"></path>'+
'<path d="M 80 60 v 40" fill="none" stroke="#000fff" stroke-width="1" id="ggpath_4"></path>'
svgCmpt.size.width = 100
svgCmpt.size.height = 100
svgCmpt.cmptType = 2
switch (instr.type) {
// 输入
case 'in':
svgCmpt.modulePos = 193
break;
// 输出
case 'out':
svgCmpt.modulePos = 197
break;
}
for (var i = 0; i < 4; i++) {
var foot ={}
foot ={id: 'node_'+i+'_foot_'+instr.type,index:i,pos:svgCmpt.modulePos,x:20+i*20,y:100}
svgCmpt.foots.push(foot)
}
isAddCmpt = true; // 开启添加器件
if (typeof(instr.addCallback) == 'function') {
svgCmpt.addCallback = function(){
instr.addCallback()
}
}
if (typeof(instr.delCallback) == 'function') {
svgCmpt.delCallback = function(){
instr.delCallback()
}
}
activeCmpt = svgCmpt;
}
//删除器件方法
this.removeCmpt=function(SvgCmpt){
SvgCmpt.isDelFlag = true;
}
//添加连线方法
this.addCircuit=function(circuit){
this.circuits.push(circuit)
}
//删除连线方法
this.removeCircuit=function(i){
this.circuits.splice(i,1)
}
// 开启连线
this.createRootPath=function(e,circle,cmpt){
isComplatePath = false;
// 偏移坐标
var t = circle.parent().parent().transform()
// 绝对坐标
var x = circle.attr('cx') + t.e , y =circle.attr('cy') + t.f;
var groupId = uuid19()
var group = polylineGroup.group().id(groupId)
var circuit = new SvgCircuit();
circuit.startFoot = circle;
circuit.startPos = circle.attr('id').split('_')[1]
circuit.startCmpt = cmpt
circuit.groupId = groupId
var polyline = svgRoot.polyline(x+','+y+' '+(x+10)+','+y+' '+(x+10)+','+(y+10)).stroke('#800').fill('none').stroke({ width: 1 })
group.add(polyline);
circuit.group = group
currentFootTransform = t;
currentPolyline = polyline
currentPolylineObj = circuit;
}
// 完成连线
this.finishLine=function(isSuccess){
if (isSuccess) {
// 连线编辑功能
var p = currentPolyline
var o = currentPolylineObj
p.on('mouseup',function(e){
isEditPolyline = true
p.stroke('#ff0000')
editPolyLine = o
})
p.on('mouseover',function(e){
if (!isMulSelect) {
selectPolylines.push(o)
p.stroke('#ff0000')
}
})
p.on('mouseout',function(e){
if (!isMulSelect && !isEditPolyline) {
selectPolylines = []
p.stroke('#800')
}
})
//执行添加连线回调
$('#sendState').show();
}
crossLine_X.plot('M0 0')
crossLine_Y.plot('M0 0')
isComplatePath = true;
currentFootTransform = null;
currentPolyline = null;
currentPolylineObj = null;
}
// 连线优化函数
this.optimizePolyline=function(points){
var l = points.length
for (var i = 1; i < l-4;i++) {
var preP = points[i].split(',')
var midP = points[i+1].split(',')
var aP = points[i+2].split(',')
// 删除无用的中间点
if ((preP[0] == midP[0] && midP[0] == aP[0]) || (preP[1] == midP[1] && midP[1]== aP[1])) {
points.splice(i+1,1)
}
}
return points;
}
//重置画布方法
this.resetPage=function(){
svgRootGroup.clear()
selectCmpt = null; // 选中器件列表
selectCmpts = []; // 选中多个器件
selectLines = null; // 选中的连线
selectPolylines = []; // 选中多条连线
originScale = 1; // 原始比例
isComplatePath = true; // 绘制连线
isSelectBox = false;// 矩形拉选
isMulSelect = false;// 是否处于多选状态
isMoveMulSelect = false; // 是否开启批量移动
changeLineX = false; // 连线X变向
changeLineY = false; // 连线Y变向
isAddCmpt = false; // 是否处于添加器件状态
activeCmpt = null; // 刚添加器件
svgRoot.attr('transform','scale('+originScale+')') // 初始化画板比例
_this.cmpts.forEach(function(cmpt){
if (typeof(cmpt.delCallback) == 'function') {
cmpt.delCallback()
}
})
_this.cmpts.splice(0)
_this.circuits.splice(0)
defs = svgRoot.defs()
svgRootGroup.add(gridRect)
polylineGroup = svgRootGroup.group().id('polylinegroup')
_this.finishLine(false)
}
}