使用gojs拖拽可视化图形

电力一次接线图主要表示配电站内各电力设备相互连接关系,并可以实时显示配电设备的电气量。在电力设备运维中也可以通过一次图进行设备的远程遥控。

本文基于原生JS,采用GoJS v1.8.16 +svg实现自定义的图元设计和可拖拽的页面设计。

支持在vue/html里直接嵌套

封装后的前端代码如下:

核心js代码:

//图片路径
var imgUrl = "./img/elements/";

var SD = {
	itemType: "",
	mode: "pointer",
	node: ""
};
// 画板对象
var palette;
var GO;
// 复制对象
// var copyData=[]
// var oldJson
// var dataAll={}
// 拷贝默认次数
var clipboardPastedTimes = 1;
// 点、线、文本(默认存在)
var defaultElement = {
	"point": {
		"key": "point",
		"category": "point",
		"group": "point",
		"text": "点",
		"tooltip": "点",
		"img": "point.png",
		"fill": "#f00",
		"stroke": null,
		"default": true
	},
	"line": {
		"key": "line",
		"category": "line",
		"group": "line",
		"text": "线",
		"tooltip": "线",
		"img": "line.png",
		"fill": null,
		"stroke": "#f00",
		"strokeWidth":3,
		"default": true
	},
	"dottedline": {
		"key": "dottedline",
		"category": 'dottedline',
		"name": "dottedline",
		"group": "line",
		"text": "虚线",
		"tooltip": "___ ___ ___ ___",
		"img": "dottedline.png",
		"fill": null,
		"stroke": "#f00",
		"strokeWidth":3,
		"default": true
	},
	// 矩形
	"rectangle": {
		"key": "rectangle",
		"category": "rectangle",
		"group": "line",
		"name": "rectangle",
		 "text": "矩形",
		"tooltip": "矩形",
		"img": "rectangle.png",
		"fill": null,
		"stroke": "#f00",
		"strokeWidth":3,
		"default": true
	},
	
	"text": {
		"key": "text",
		"group": "text",
		"name": "text",
		"category": "text",
		"text": "文本",
		"tooltip": "文本",
		"img": "text.png",
		"stroke": "#fff",
		"font": "bold 14pt serif",
		"default": true
	},
	"time": {
		"key": "time",
		"group": "time",
		"name": "time",
		"category": "time",
		 "text": "日期",
		"tooltip": "日期",
		"img": "date.png",
		"stroke": "#fff",
		"font": "bold 14pt serif",
		"default": true
	},
	// "picture": {
	// 	"key": "picture",
	// 	"group": "picture",
	// 	"name": "picture",
	// 	"category": "picture",
	// 	"text": "图片",
	// 	"tooltip": "图片",
	// 	// "source":base64Url,
	// 	// "source":"text.png",
	// 	"default": true
	// },
};
    var chartJson
	var stationId 
	var background  
$(function() {
	$('#palette').css('backgroundColor','#000')
	let id =localStorage.getItem('id')
	$('.pageId').attr('value',id)
	 if(id!=0&&!id){
		 return
	 }
		function getBaseList(){
            $.ajax({
				url: url_global2+"/drawing/charts/" + id ,
				type: "GET",
				success: function(result) {
				   chartJson=result.json
				   stationId = result.stationId
				   background= result.background
				  
				   initPalette()
				  
				   initLeftElements(function(data) {
		
					// 交互操作
					initOperate();
					// 初始化中间画板
	                // initPalette();
	                // 初始化左侧图元栏
	                $('#pixelContainer').niceScroll({
	                	cursorcolor: "#9fdbe5",
	                	cursoropacitymax: 1,
	                	touchbehavior: false,
	                	cursorwidth: "4px",
	                	cursorborder: "0",
	                	cursorborderradius: "0",
	                	autohidemode: false
	                });
					// 初始化右边的palette
					initPaletteElement(data);
					// dataAll=data
					 //节点的详情编辑及显示---属性框
					new Inspector('inspectorInfo', palette);
			
					if(chartJson) {
						palette.model = go.Model.fromJson(chartJson);
					}
				})
				},
				error: function(response) {
				}
			})
		}
		getBaseList()
});
// 初始化左边的图元
function initLeftElements(callback) {
	$.ajax({
		type: "get",
		url: url_global2+"/drawing/elements",
		contentType: "application/json",
		cache: false,
		success: function(data) {
			var elements = $.extend({},
				data);
			for(var dataKey in data) {
				if(data[dataKey].is_deleted != null && data[dataKey].is_deleted) {
					delete data[dataKey];
				}
			}
			data = $.extend({},
				defaultElement, data);
			initPixel(data,
				function(element) {
					setMode('node', element);
				},
				function(obj, element) {
					if(obj.attr("key") == "pointer") {
						setMode('pointer', 'pointer');
					} else {
						setMode('node', element);
					}
				},
				true);
			if(callback) callback(elements);
		}
	});

	// 属性栏的关闭时间
	$("#closeAttr").click(function() {
		$("#attrWrapper").hide();
	});

	//属性栏拖拽移动
	var $dialog = $("#attrWrapper");
	var $dataModal = $("#dataModal");
	//声明需要用到的变量
	var mx = 0,
		my = 0; //鼠标x、y轴坐标(相对于left,top)
	var dx = 0,
		dy = 0; //对话框坐标(同上)
	var isDraging = false; //不可拖动

	//鼠标按下
	$("#move_part").mousedown(function(e) {
		e = e || window.event;
		mx = e.pageX; //点击时鼠标X坐标
		my = e.pageY; //点击时鼠标Y坐标
		dx = $dialog.offset().left;
		dy = $dialog.offset().top;
		isDraging = true; //标记对话框可拖动                
	});
	

	//鼠标移动更新窗口位置
	$(document).mousemove(function(e) {
		var e = e || window.event;
		var x = e.pageX; //移动时鼠标X坐标
		var y = e.pageY; //移动时鼠标Y坐标
		if(isDraging) { //判断对话框能否拖动
			var moveX = dx + x - mx; //移动后对话框新的left值
			var moveY = dy + y - my; //移动后对话框新的top值
			//设置拖动范围
			var pageW = $(window).width();
			var pageH = $(window).height();

			var dialogW = $dialog.width();
			var dialogH = $dialog.height();

           //var dialogMW = $dataModal.width();
           //var dialogMH = $dataModal.height();

			var maxX = pageW - dialogW; //X轴可拖动最大值
			var maxY = pageH - dialogH; //Y轴可拖动最大值
			
           //var maxMX = pageW - dialogMW; //X轴可拖动最大值
           //var maxMY = pageH - dialogMH; //Y轴可拖动最大值

			//moveX = Math.min(Math.max(0, moveX), maxX); //X轴可拖动范围
			//moveY = Math.min(Math.max(0, moveY), maxY); //Y轴可拖动范围
			//重新设置对话框的left、top
			$dialog.css({
				"left": Math.min(Math.max(0, moveX), maxX) + 'px',
				"top": Math.min(Math.max(0, moveY), maxY) + 'px'
			});
            //$dataModal.css({
            //	"left": Math.min(Math.max(0, moveX), maxMX) + 'px',
            //	"top": Math.min(Math.max(0, moveY), maxMY) + 'px'
            //	});
		};
	});
	//鼠标离开
	$("#move_part").mouseup(function() {
		isDraging = false;
	});
	initDataModal();
	elementHandle();
	if(background) {
		$("#palette").css({
			"background-image": "url('data:image/png;base64," + background + "')",
			"backgroundSize": "100% 100%"
		});
	}
}

// 图元操作
function elementHandle() {
	$("#attrWrapper").css('display', 'block');
	$(".form-color").change(function() {
		$(this).prev(".form-color-val").val($(this).val());
	});
	$(".form-color-val").change(function() {
		$(this).next(".form-color").val($(this).val());
	})

	// 添加
	$("#add").off("click").click(function() {
		$("#addModal").modal({
			close: clearForm,
			ok: addChartElement
		});
	});

	//修改
	$("#update").off("click").click(function() {
		if(SD.node) {
			if(SD.node == "pointer" || SD.node.category == "line" || SD.node.category == "point") {
				$.ele.alert("此图元不可进行操作");
				return;
			}
			// console.log(SD.node.img,'SD.node.img',SD.node,'SD.node');
		     $('.modal-title').text('修改图元')
			$("#group").val(SD.node.group);
			$("#text").val(SD.node.text);
			$("#category").val(SD.node.category);
			$("#type").val(SD.node.type);
			$("#tooltip").val(SD.node.tooltip);
			$("#fill").val(SD.node.fill);
			$("#fill").next(".form-color").val(SD.node.fill);
			$("#stroke").val(SD.node.stroke);
			$("#stroke").next(".form-color").val(SD.node.stroke);
			$("#font").val(SD.node.font);
			$("#ports").val(SD.node.ports);
			$("#svg").val(SD.node.svg);
			$("#iconImg").attr("src", "data:image/png;base64," + SD.node.img);
			$("#iconImg").show();
			$("input[name='status'][value=" + SD.node.status + "]").attr("checked", true);
		
			$("#addModal").modal({
				close: clearForm,//取消或关闭
				ok: updateChartElement//成功
			});
		
		} else {
			$.ele.alert("请点击要修改的图元");
		}
	});

	// 导入
	$("#import").off("click").click(function() {
		$("#importModal").modal();
	});

	// 导出
	$("#export").off("click").click(function() {
		$.ele.confirm("导出", "确认导出图元列表JSON文件吗?",
			function(result) {
				if(result) {
					window.open(url_global2+"/drawing/elements/export");
				}
			});
	});

	// 删除
	$("#del").off("click").click(function() {
		if(SD.node) {
			if(SD.node == "pointer" || SD.node.category == "line" || SD.node.category == "point") {
				$.ele.alert("此图元不可进行操作");
				return;
			}
			$.ele.confirm("删除", "确认删除此图元吗?",
				function(result) {
					if(result) {
						$.ajax({
							url: url_global2+"/drawing/elements/" + SD.node.id,
							type: "DELETE",
							success: function(result) {
								$.ele.alert("删除成功");
								
								initLeftElements();
							},
							error: function(response) {
								// console.log(response);
							}
						})
					} else {
						$.ele.alert("取消删除");
					}
				});
		} else {
			$.ele.alert("请点击要删除的图元");
		}
	});
}
// 清空form
function clearForm() {
	$(".form-color").val("");
	$("#iconImg").removeAttr("src").hide();
	$('#add-form')[0].reset();
	$('.modal-title').text('添加图元')
	// console.log('clearForm()');

}

// 初始化中间画板
function initPalette() {

	GO = go.GraphObject.make;
 
	palette = GO(go.Diagram, "palette", {
		grid: GO(go.Panel, "Grid", GO(go.Shape, "LineH", {
			stroke: "lightgray",
			strokeWidth: 0.5
		}), GO(go.Shape, "LineH", {
			stroke: "gray",
			strokeWidth: 0.5,
			interval: 10
		}), GO(go.Shape, "LineV", {
			stroke: "lightgray",
			strokeWidth: 0.5
		}), GO(go.Shape, "LineV", {
			stroke: "gray",
			strokeWidth: 0.5,
			interval: 10
		})),
		initialAutoScale:go.Diagram.Uniform,
		initialContentAlignment: go.Spot.Center,
		allowZoom: true,
		allowDrop: true,
		commandHandler: new DrawCommandHandler(),
		"draggingTool.dragsLink": true,
		"draggingTool.isGridSnapEnabled": true,
		"linkingTool.isUnconnectedLinkValid": true,
		"linkingTool.insertLink": function(fromnode, fromport, tonode, toport) {
			this.archetypeLinkData.stroke = "#f00";
			return go.LinkingTool.prototype.insertLink.call(this, fromnode, fromport, tonode, toport);
		},
		"commandHandler.deletesTree": true,
		"linkReshapingTool.handleArchetype": GO(go.Shape, "Diamond", {
			desiredSize: new go.Size(7, 7),
			fill: "lightblue",
			stroke: "deepskyblue"
		}),
		rotatingTool: GO(TopRotatingTool),
		"clickCreatingTool.archetypeNodeData": {},
		"clickCreatingTool.isDoubleClick": false,
		"clickCreatingTool.canStart": function() {
			return SD.mode === "node" && go.ClickCreatingTool.prototype.canStart.call(this);
		},
		"clickCreatingTool.insertPart": function(loc) {
			var newNode = SD.node;
			// console.log(newNode);
			this.archetypeNodeData = {
				key: newNode.category,
				category: newNode.category,
				label: newNode.text,
				fill: newNode.fill || null,
				stroke: newNode.stroke || null,
				name: newNode.name,
				tooltip: newNode.tooltip,
				font: newNode.font || "",
				strokeWidth:newNode.strokeWidth
			};

			return go.ClickCreatingTool.prototype.insertPart.call(this, loc);
		},
		// "ClipboardChanged":isClipboardChanged,//ctrl+c
		// "BackgroundSingleClicked":isBackgroundSingleClicked,
		// "BackgroundContextClicked":isBackgroundContextClicked,
	});

	palette.toolManager.mouseMoveTools.insertAt(0, new NodeLabelDraggingTool());
	palette.undoManager.isEnabled = true;
	var linkSelectionAdornmentTemplate = GO(go.Adornment, "Link", GO(go.Shape, {
		isPanelMain: true,
		fill: null,
		stroke: null,
		strokeWidth: 0
	}));

	palette.linkTemplate = GO(go.Link, {
			selectable: true,
			selectionAdornmentTemplate: linkSelectionAdornmentTemplate
		}, {
			relinkableFrom: true,
			relinkableTo: true,
			reshapable: true,
			resegmentable: true
		}, {
			routing: go.Link.AvoidsNodes,
			curve: go.Link.None,
			corner: 0,
			toShortLength: -2,
			fromShortLength: -2,
			toEndSegmentLength: 0
		},
		new go.Binding("points").makeTwoWay(), GO(go.Shape, {
				isPanelMain: true,
				strokeWidth: 2
			},
			new go.Binding("stroke", "stroke")));

	// 拷贝图元粘贴时与原图元错位
	palette.addDiagramListener("ClipboardChanged",
		function(e) {
			clipboardPastedTimes = 1;
		});

	/*palette.addDiagramListener("ClipboardPasted",
		function(e) {
			if(palette.selection && palette.selection.size == 1) {
				palette.selection.each(function(n) {
					if(n instanceof go.Node && n.isSelected) {
						var position = n.location.copy();
						position.x += clipboardPastedTimes * 10;
						position.y += clipboardPastedTimes * 10;
						n.location = position;
						clipboardPastedTimes++;
						return;
					}
				});
			}
		});*/
}

// 设置对齐
function setAlign(align) {
	var left, right, top, bottom, centerOfX, centerOfY;
	var totalOfX = 0;
	var totalOfY = 0;

	if(palette.selection.size == 0) {
		return;
	}

	palette.selection.each(function(n) {
		if(n instanceof go.Node) {
			var x = n.location.x;
			var y = n.location.y;

			left = left < x ? left : x;
			right = right > x ? right : x;
			top = top < y ? top : y;
			bottom = bottom > y ? bottom : y;
			totalOfX += x;
			totalOfY += y;
		}
	});
	centerOfX = totalOfX / palette.selection.size;
	centerOfY = totalOfY / palette.selection.size;

	palette.startTransaction("align");

	palette.selection.each(function(n) {
		if(n instanceof go.Node) {
			var position = n.location.copy();
			switch(align) {
				case "left":
					if(left) {
						position.x = left;
					}
					break;
				case "right":
					if(right) {
						position.x = right;
					}
					break;
				case "top":
					if(top) {
						position.y = top;
					}
					break;
				case "bottom":
					if(bottom) {
						position.y = bottom;
					}
					break;
				case "middle":
					if(centerOfY) {
						position.y = centerOfY;
					}
					break;
				case "center":
					if(centerOfX) {
						position.x = centerOfX;
					}
					break;
			}
			n.location = position;
		}
	});
	palette.commitTransaction("align");
}
// 设置分布
function setDistribution(distribution) {
	var totalOfX = 0;
	var totalOfY = 0;
	var arrayX = new Array();
	var arrayY = new Array();

	if(palette.selection.size == 0) {
		return;
	}

	palette.selection.each(function(n) {
		arrayX.push(n);
		arrayY.push(n);
	});

	arrayX.sort(function(a, b) {
		if(a && b) {
			return a.location.x > b.location.x;
		}
	});
	arrayY.sort(function(a, b) {
		if(a && b) {
			return a.location.y > b.location.y;
		}
	});

	totalOfX = arrayX[arrayX.length - 1].location.x - arrayX[0].location.x;
	totalOfY = arrayY[arrayY.length - 1].location.y - arrayY[0].location.y;

	palette.startTransaction("distribution");

	switch(distribution) {
		case "horizontal":
			$(arrayX).each(function(i, n) {
				if(i == 0 || i == arrayX.length - 1) return;
				if(n instanceof go.Node) {
					var position = n.location.copy();
					position.x = arrayX[0].location.x + (i / (arrayX.length - 1)) * totalOfX;
					n.location = position;
				}
			});
			break;
		case "vertical":
			$(arrayY).each(function(i, n) {
				if(i == 0 || i == arrayY.length - 1) return;
				if(n instanceof go.Node) {
					var position = n.location.copy();
					position.y = arrayY[0].location.y + ((i / (arrayY.length - 1)) * totalOfY);
					n.location = position;
				}
			});
			break;
	}

	palette.commitTransaction("distribution");
}
// 点击在画布绘制图元 mode == node/link , itemType = variable/cloud
function setMode(mode, node) {
	// console.log(mode, node,'mode, node');
	palette.startTransaction();
	SD.mode = mode;
	SD.node = node;
	console.log(SD,'SD');
	if(mode === "pointer") {
		palette.allowLink = false;
		palette.nodes.each(function(n) {
			n.port.cursor = "";
		});
	} else if(mode === "node") {
		// console.log(palette.nodes,'palette.nodes');
		palette.allowLink = false;
		palette.nodes.each(function(n) {
			// console.log(n);
			n.port.cursor = "";
		});
	}
	palette.commitTransaction("mode changed");
}
// 选中图元操作-样式
function TopRotatingTool() {
	go.RotatingTool.call(this);
}
go.Diagram.inherit(TopRotatingTool, go.RotatingTool);
TopRotatingTool.prototype.updateAdornments = function(part) {
	go.RotatingTool.prototype.updateAdornments.call(this, part);
	var adornment = part.findAdornment("Rotating");
	if(adornment !== null) {
		adornment.location = part.rotateObject.getDocumentPoint(new go.Spot(0.5, 0, 0, -30)); // above middle top
	}
};
TopRotatingTool.prototype.rotate = function(newangle) {
	go.RotatingTool.prototype.rotate.call(this, newangle + 90);
};

function preview() {
	 
	$("#previewModal").modal({
		width: $(".palette-wrapper").width(),
		height: $(".palette-wrapper").height() - 60,
		top: 0
	});
	$(".preview-chart").html(palette.makeSvg({
		scale: 1
	}));
}

function zoomIn() {
	var zoomVal = parseInt($("#zoomVal").text());
	if(zoomVal <= 10) {
		return;
	}
	$("#zoomVal").text(zoomVal - 10);
	palette.commandHandler.decreaseZoom();
	$(".preview-chart").html(palette.makeSvg());
}

function zoomOut() {
	var zoomVal = parseInt($("#zoomVal").text());
	if(zoomVal >= 300) {
		return;
	}
	$("#zoomVal").text(zoomVal + 10);
	palette.commandHandler.increaseZoom();
	$(".preview-chart").html(palette.makeSvg());
}
//保存一次图
function saveJson() {
	var data = {
		json: palette.model.toJson()
	}
	// console.log(palette.model.toJson());
	// console.log(data);
	$.ajax({
		type: "put",
		url:url_global2+ "/drawing/charts/" + $("#chartId").val(),
		data: JSON.stringify(data),
		contentType: "application/json",
		cache: false,
		success: function(data) {
			if(data.code==500){
				$.ele.alert("保存失败");
				return
			}
			$.ele.alert("保存成功");
		},
		error: function(err) {
			$.ele.alert("导入失败");
		}
	});
}

function reset() {
	$.ele.confirm("重置", "确认将接线图重置为空吗?",
		function(result) {
			if(result) {
				palette.commandHandler.selectAll();
				palette.commandHandler.deleteSelection();
			}
		});
}
// 选择图片
function chooseIcon() {
	var icon = "";
	var file = document.getElementById("icon").files[0];
	if(file) {
		if(!/image\/\w+/.test(file.type)) {
			alert("请确保文件为图像文件");
			return false;
		}
		var reader = new FileReader();
		reader.readAsDataURL(file);
		reader.onload = function() {
			if(reader && reader.result) {
				$("#iconImg").attr("src", reader.result);
				$("#iconImg").show();
			}
		}
	}
}

// 添加图元
function addChartElement() {
	var img = $("#iconImg").attr("src") || "";
    // console.log($("#group").val(),$("#text").val(),$("#category").val(),img);
	
	
	if($("#group").val()==''){
		$.ele.alert("请填写分组");
		return
	}else if($("#category").val()==''){
		$.ele.alert("请填写图元类别");
		return
	}else if($("#text").val()==''){
		$.ele.alert("请填写名称");
	}else if(img==''){
		$.ele.alert("请选择图标");
		return
	}
	var params = {
		"group": $("#group").val(),
		"text": $("#text").val(),
		"category": $("#category").val(),
		"type": $("#type").val(),
		"tooltip": $("#tooltip").val(),
		"fill": $("#fill").val(),
		"stroke": $("#stroke").val(),
		"font": $("#font").val(),
		"ports": $("#ports").val().split(","),
		"svg": $("#svg").val(),
		"img": img.substring(img.indexOf("base64,") + 7),
		"status": $("input[name='status']").val()
	};

	$.ajax({
		url: url_global2+"/drawing/elements",
		data: JSON.stringify(params),
		type: "Post",
		dataType: "json",
		contentType: "application/json; charset=utf-8",
		success: function(result) {
			
			if(result.code==500){
				$.ele.alert("添加失败");
				return
			}
			initLeftElements();
			$("#addModal").modal('hide');
			$.ele.alert("添加成功");
			clearForm()
		},
		error: function(response) {
			// console.log(response);
			$.ele.alert("添加失败");
		}
	})

	/*
	 * palette.commandHandler.selectAll();
	 * palette.commandHandler.deleteSelection();
	 */
}
// 修改图元
function updateChartElement() {
	$('.modal-title').text('添加图元')
	var img = $("#iconImg").attr("src") || "";
	// console.log(img);
	var params = {
		"group": $("#group").val(),
		"text": $("#text").val(),
		"category": $("#category").val(),
		"type": $("#type").val(),
		"tooltip": $("#tooltip").val(),
		"fill": $("#fill").val(),
		"stroke": $("#stroke").val(),
		"font": $("#font").val(),
		"ports": $("#ports").val().split(","),
		"svg": $("#svg").val(),
		"img": img.substring(img.indexOf("base64,") + 7),
		"status": $("input[name='status']").val()
	};

	$.ajax({
		url:url_global2+ "/drawing/elements/" + SD.node.id,
		data: JSON.stringify(params),
		type: "PUT",
		dataType: "json",
		contentType: "application/json; charset=utf-8",
		success: function(result) {
		    if(result.code==500){
				$.ele.alert("修改失败");
				clearForm()
			}
			$("#addModal").modal('hide');
			$.ele.alert("修改成功");
			initLeftElements();
			clearForm()
		},
		error: function(response) {
			// console.log(response);
		}
	});
}

$('#device-list').on('click','input',function(){
	$("input[name='checkbox']").prop('checked', false);
	$(this).prop('checked', true)
	// console.log($(this));
})

function initDataModal() {
	$("#device-list").on("click", "tr", function() {
		$("#device-list").find("tr").removeClass("active");
		$(this).addClass("active");
	});
   
	$("#dataModal select[name='substation']").html("");
	$.ajax({
		type: "get",
		url:url_global2+ "/drawing/substations",
		contentType: "application/json",
		cache: false,
		success: function(data) {
			$("#dataModal select[name='substation']").append("<option value=''>请选择</option>");
			if(data) {
				$.each(data,
					function(i, n) {
						$("#dataModal select[name='substation']").append("<option value='" + n.id + "'>" + n.name + "</option>");
					});
			}
		}
	});
	// 获取摄像机list
	function getCameraList(callback){
        $("#device-list").html("");
		if(!$("#dataModal select[name='substation']").val()&&$("#dataModal select[name='substation']").val()!=0){
			return
		}
		var params={
			fStationid:$("#dataModal select[name='substation']").val(),
		}
		$.ajax({
			type:"get",
			url:url_global2+"/biz/vedio/getCameraListByStation",
			data:params,
			contentType:'application/json',
			caches:false,
			success:function(res){
				if(res.code==500){	return}
				if(res.data){
					var substationText = $("#dataModal select[name='substation']").val() ? $("#dataModal select[name='substation'] option:selected").text() : "-";
					var typeText = $("#dataModal select[name='type']").val() ? $("#dataModal select[name='type'] option:selected").text() : "-";
					$.each(res.data,function(i,n){
						var tr=$("<tr>");
						tr.data("device-id", n.videoId);
						tr.append($("<td>").append($('<input type="checkbox" class="iptCheck" name="checkbox" value="'+ n.videoId +'" />')))
						tr.append($("<td>").text(n.videoId).attr("title", n.videoId));
						tr.append($("<td name='name'>").text(n.wayName).attr("title", n.wayName));
						var attribute = $("<select name='attribute'>");
						let atterArr=["value", "status"]
						$.each(atterArr,function(ii, nn) {
							attribute.append($("<option>").text(nn).val(nn));
						});
						tr.append($("<td>").append(attribute));
						$("#device-list").append(tr);
					})
				}
				callback&&callback()
				
			}
		})
	}
    // 获取四遥设备list
	function getDevice(callback) {
		$("#device-list").html("");
		var param = {
			substation: $("#dataModal select[name='substation']").val(),
			type: $("#dataModal select[name='type']").val()
		};

		$.ajax({
			type: "get",
			url: url_global2+"/drawing/devices",
			data: param,
			contentType: "application/json",
			cache: false,
			success: function(data) {
				if(data.code==500){
					return
				}
				if(data) {
					var substationText = $("#dataModal select[name='substation']").val() ? $("#dataModal select[name='substation'] option:selected").text() : "-";
					var typeText = $("#dataModal select[name='type']").val() ? $("#dataModal select[name='type'] option:selected").text() : "-";
					$.each(data,
						function(i, n) {
							var tr = $("<tr>");
							tr.data("device-id", n.id);
							tr.append($("<td>").append($('<input type="checkbox" class="iptCheck" name="checkbox" value="'+ n.id +'" />')))
							// tr.append($("<td>").text(substationText).attr("title", substationText));
							// tr.append($("<td>").text(typeText).attr("title", typeText));
							tr.append($("<td>").text(n.id).attr("title", n.id));
							tr.append($("<td name='name'>").text(n.name).attr("title", n.name));

							var attribute = $("<select name='attribute'>");
							if(n.attributes) {
								$.each(n.attributes,
									function(ii, nn) {
										attribute.append($("<option>").text(nn).val(nn));
									});
							}
							tr.append($("<td>").append(attribute));
							$("#device-list").append(tr);
						});
					callback();
				}
			}
		});
	}
   
	function filterDevice() {
		var search = $("#dataModal input[name='search']").val();
		var search2 = $("#dataModal input[name='search2']").val();
		$("#device-list tr").each(function(i, n) {
			if($(n).find("td[name='name']:contains('" + search + "')").length != 0 &&$(n).find("td[name='name']:contains('" + search2 + "')").length != 0) {
				$(n).show();
			} else {
				$(n).hide();
			}
		});
	}
    // 数据绑定厂站改变获取设备列表
	$("#dataModal select[name='substation']").change(function() {
		var typeValue =$("#dataModal select[name='type']").val();
		if(typeValue==6){
			getCameraList(function() {
				filterDevice();
			})
		}else{
		  getDevice(function() {
		  	filterDevice();
		  });
		}  
	});
	// 数据绑定类型改变
	$("#dataModal select[name='type']").change(function() {
		var typeValue = $(this).val();
		// 摄像头类型
		if(typeValue==6){
			getCameraList(function(){
				filterDevice() 
				$("#dataModal #device-list select[name='attribute'] option[value='value']").attr("selected", "selected");
			})
		}else{
			getDevice(function() {
				filterDevice();
				if(typeValue == 2) {
					$("#dataModal #device-list select[name='attribute'] option[value='status']").attr("selected", "selected");
					//    			$("#dataModal #device-list select[name='attribute'] option[value='value']").attr("selected","selected");
					//    			$("#dataModal #device-list select[name='attribute'] option[value!='value']").attr("disabled","disabled");
					//    		}else if(typeValue == 2){
					//    			$("#dataModal #device-list select[name='attribute'] option[value='status']").attr("selected","selected");
					    			$("#dataModal #device-list select[name='attribute'] option[value!='status']").attr("disabled","disabled");
				} else {
					$("#dataModal #device-list select[name='attribute'] option[value='value']").attr("selected", "selected");
					//    			$("#dataModal #device-list select[name='attribute'] option[value!='value']").attr("disabled","disabled");
				}
			});
		}
		
	});

	$("#dataModal input[name='search']").keyup(function() {
		filterDevice();
	});
	$("#dataModal input[name='search2']").keyup(function() {
		filterDevice();
	});
}

function deleteBind() {
	$.ajax({
		type: "delete",
		url: url_global2+"/drawing/charts/" + $("#chartId").val() + "/bind/" + $("#device-list").data("key"),
		contentType: "application/json",
		cache: false,
		success: function(data) {
			$("#dataModal").modal('hide');
			$('.modal-body').scrollTop(0)
			
		}
	});
}

function saveBind() {
    let that =this
	var typeValue =$("#dataModal select[name='type']").val();
	if($("#device-list tr.active").length == 0) {
		$.ele.alert("绑定数据不能为空");
		return;
	}

	var data = {
		elementCategory: $("#device-list").data("category"),
		elementKey: $("#device-list").data("key"),
		deviceId: $("#device-list tr.active").data("device-id"),
		deviceAttribute: $("#device-list tr.active select[name='attribute']").val(),
		deviceName: $("#device-list tr.active td[name='name']").text(),
		type:$("#dataModal select[name='type']").val()
	};

	$.ajax({
		type: "post",
		url: url_global2+"/drawing/charts/" + $("#chartId").val() + "/bind",
		data: JSON.stringify(data),
		contentType: "application/json",
		cache: false,
		success: function(data) {
			$("#dataModal").modal('hide');
			$('.modal-body').scrollTop(0)	
			
		}
	});
	
}

封装后的java后台代码如下:

实现的效果

学习交流Q1946647866

  • 19
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行微调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面三个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心编码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值