Vue中使用GOJS绘制拓扑图(项目实践)
Vue中使用gojs绘画拓扑图
·
1、首先下载GOJS
npm install gojs --save
2、Vue中使用
import gojs from "gojs";
var go = gojs;
var $ = go.GraphObject.make;
//代码所需要的JSON格式
import json from "./json";
//项目中应用到的图片
import zhong from "@/assets/basic/zhong.png";
import da from "@/assets/basic/da.png";
import xiao from "@/assets/basic/xiao.png";
3、将注册实例以及业务代码编写再init函数中在mounted挂载中调用
init() {
// 结合后端数据进行 赋值各项不同节点的与图片文字
json["nodeDataArray"].forEach((item) => {
switch (+item.size) {
case 100:
item.source = xiao;
item.stroke = item.type === "0" ? "red" : "#56b1ff";
break;
case 150:
item.source = zhong;
item.stroke = "#fff";
break;
case 200:
item.source = da;
item.stroke = "#fff";
break;
default:
item.source = xiao;
break;
}
if (item.type === "0") {
item.stroke = "red";
}
});
// 判断实例是否存在进行数据变更
if (this.myDiagram) {
this.myDiagram.model = go.Model.fromJson(json);
return;
}
this.myDiagram = $(
go.Diagram,
this.$refs.myDiagram, //获取原生dom进行gojs的注入
{
"undoManager.isEnabled": true, //是否可以进行撤销等操作
// "undoManager.isEnabled": false,
initialContentAlignment: go.Spot.Center, //启动视口中间的所有内容
// "toolManager.mouseWheelBehavior": go.ToolManager.WheelNone, //鼠标滚轮事件禁止
"toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom, //开启滚轮事件
// allowHorizontalScroll: false, //禁止水平拖动
// allowVerticalScroll: false, // 禁止垂直拖动
// isReadOnly: true, //是否为只读状态
minScale: 0.2, // 缩小临界值
maxScale: 1.5, //放大临街值
scale: 0.38, //初始视图大小比例
LinkDrawn: this.maybeChangeLinkCategory, // 连线判断
LinkRelinked: this.maybeChangeLinkCategory, // 连线判断
}
);
const portSize = new go.Size(6, 6); //小节点大小
var _that = this;
// 给节点的设置右键按钮 // nodeMenu上下文菜单
const nodeMenu = $(
"ContextMenu",
this.makeButton("复制", (e, obj) =>
e.diagram.commandHandler.copySelection()
),
this.makeButton("粘贴", (e, obj) =>
e.diagram.commandHandler.pasteSelection()
),
this.makeButton("删除", (e, obj) =>
e.diagram.commandHandler.deleteSelection()
),
this.makeButton("更改背景", (e, obj) =>
this.changeBackground(obj.part.adornedObject)
),
this.makeButton("添加头部小节点", (e, obj) => this.addPort("top")),
this.makeButton("添加左侧小节点", (e, obj) => this.addPort("left")),
this.makeButton("添加右侧小节点", (e, obj) => this.addPort("right")),
this.makeButton("添加底部小节点", (e, obj) => this.addPort("bottom"))
);
// 给小节点(端口)设置删除
const portMenu = $(
"ContextMenu",
this.makeButton("更改小节点颜色", (e, obj) =>
this.changeColor(obj.part.adornedObject)
),
this.makeButton(
"删除小节点",
// 在click事件处理程序中,obj。一部分是装饰;
// 它的父对象是端口
(e, obj) => this.removePort(obj.part.adornedObject)
),
this.makeButton("删除全部小节点", (e, obj) =>
this.removeAll(obj.part.adornedObject)
)
);
// 节点模板
this.myDiagram.nodeTemplate = $(
go.Node,
"Table",
{
locationObjectName: "BODY",
locationSpot: go.Spot.Center, //将节点放置中间
selectionObjectName: "BODY",
contextMenu: nodeMenu, // 去除右键
},
// 动态绑定位置信息
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(
go.Point.stringify
),
// 声明面板 the body
$(
go.Panel,
"Auto",
// 面板默认设置
{
row: 1,
column: 1,
name: "BODY",
stretch: go.GraphObject.Fill,
},
$(
go.Picture,
{
name: "Picture",
source: zhong,
width: 100,
height: 100,
cursor: "pointer",
},
//根据JSON格式动态绑定,第三个参数接受一个函数用户业务逻辑的判断
new go.Binding("source", "source").makeTwoWay(),
new go.Binding("width", "size", (size) => {
return +size;
}),
new go.Binding("height", "size", (size) => {
return +size;
}).makeTwoWay(),
new go.Binding("name", "type").makeTwoWay()
),
// 这次我使用用的是图片代替节点样式 下面内容是设置节点样式部分
// $(
// go.Shape,
// "Circle" , //圆形
// // fn( new go.Binding('backgroud').makeTwoWay()),
// {
// name: "SHAPE",
// // 背景色和填充
// background: null,
// // 内容颜色
// fill: "#59b2fb",
// //边框色
// stroke: '#fcfafa',
// strokeWidth: 5,
// cursor: "pointer",
// // figure: "Circle",
// // Ellipse椭圆
// // 最小值
// minSize: new go.Size(42, 42),
// },
// // 动态设置
// new go.Binding("background", "backgroud").makeTwoWay(),
// // new go.Binding("geometryString", "geometryString").makeTwoWay(),
// ),
$(
go.TextBlock,
{
font: "11pt Helvetica, Arial, sans-serif",
stroke: "#fff",
cursor: "pointer",
editable: false,
},
new go.Binding("text", "name").makeTwoWay(),
new go.Binding("stroke", "stroke").makeTwoWay(),
new go.Binding("font", "size", (k) => {
switch (+k) {
case 100:
return "10pt Helvetica, Arial, sans-serif";
case 150:
return "21px Segoe UI,sans-serif";
case 200:
return "24px Segoe UI,sans-serif";
default:
return "11pt Helvetica, Arial, sans-serif";
}
})
)
),
// 设置小节点
// 绑定 itemArray leftArray
// 为itemArray中的每个项创建,并绑定到数据。左数组
$(go.Panel, "Vertical", new go.Binding("itemArray", "leftArray"), {
row: 1,
column: 0,
itemTemplate: $(
go.Panel,
{
_side: "left", //内部属性,以便更容易地判断它位于哪一侧
fromSpot: go.Spot.Left, //从左
toSpot: go.Spot.Left, //到左
fromLinkable: true,
toLinkable: true,
cursor: "pointer",
contextMenu: portMenu,
},
new go.Binding("portId", "portId"),
$(
go.Shape,
"Rectangle",
{
fill: "#2e68cc",
stroke: null,
strokeWidth: 5,
desiredSize: portSize,
margin: new go.Margin(10, -3),
},
new go.Binding("fill", "portColor")
)
),
}),
$(go.Panel, "Horizontal", new go.Binding("itemArray", "topArray"), {
row: 0,
column: 1,
itemTemplate: $(
go.Panel,
{
_side: "top",
fromSpot: go.Spot.Top,
toSpot: go.Spot.Top,
fromLinkable: true,
toLinkable: true,
cursor: "pointer",
contextMenu: portMenu,
},
new go.Binding("portId", "portId"),
$(
go.Shape,
"Rectangle",
{
stroke: null,
strokeWidth: 0,
desiredSize: portSize, //小节点大小
margin: new go.Margin(0, 10),
},
new go.Binding("fill", "portColor")
)
), // end itemTemplate
}),
$(go.Panel, "Vertical", new go.Binding("itemArray", "rightArray"), {
row: 1,
column: 2,
itemTemplate: $(
go.Panel,
{
_side: "right",
fromSpot: go.Spot.Right,
toSpot: go.Spot.Right,
fromLinkable: true,
toLinkable: true,
cursor: "pointer",
contextMenu: portMenu,
},
new go.Binding("portId", "portId"),
$(
go.Shape,
"Rectangle",
{
stroke: null,
strokeWidth: 0,
desiredSize: portSize,
margin: new go.Margin(6, 0),
},
new go.Binding("fill", "portColor")
)
), // end itemTemplate
}),
$(go.Panel, "Horizontal", new go.Binding("itemArray", "bottomArray"), {
row: 2,
column: 1,
itemTemplate: $(
go.Panel,
{
_side: "bottom",
fromSpot: go.Spot.Bottom,
toSpot: go.Spot.Bottom,
fromLinkable: true,
toLinkable: true,
cursor: "pointer",
contextMenu: portMenu,
},
new go.Binding("portId", "portId"),
$(
go.Shape,
"Rectangle",
{
stroke: null,
strokeWidth: 0,
fill: "#2e68cc",
desiredSize: portSize,
margin: new go.Margin(0, 10),
},
new go.Binding("fill", "portColor")
)
), // end itemTemplate
})
);
// 实线
this.myDiagram.linkTemplate = $(
"Link",
{
routing: go.Link.AvoidsNodes,
adjusting: go.Link.FROM,
curve: go.Link.JumpGap,
reshapable: true,
resegmentable: true,
relinkableFrom: true,
relinkableTo: true,
corner: 4,
toShortLength: 1,
cursor: "pointer",
},
new go.Binding("points").makeTwoWay(),
// 线条颜色
$(
"Shape",
{
name: "LINE",
isPanelMain: true,
stroke: "#5aaefd",
// stroke: "#01C0CA",
strokeWidth: 4,
},
new go.Binding("stroke", "color").makeTwoWay(),
new go.Binding("strokeWidth", "voltage", (item) => {
switch (item) {
case "500kV":
return 10;
case "220kV":
return 10;
case "110kV":
return 7;
default:
return 7;
}
})
),
// 用于动画效果
// $(
// "Shape",
// {
// isPanelMain: true,
// // stroke: "lightblue",
// stroke: "#01C0CA",
// // stroke: "",
// strokeWidth: 8,
// name: "DongHua",
// // 10 35
// strokeDashArray: [10, 35],
// },
// new go.Binding("stroke", "ShapeColor").makeTwoWay()
// ),
// 线路背景设置
// $(go.Shape, "RoundedRectangle", {
// name: "SHAPE",
// fill: "rgba(255,255,255,0.4)",
// height: 24,
// strokeWidth: 1,
// // stroke: "rgba(255,255,255,0.8)",
// stroke: "rgba(255,255,255,0.8)",
// }),
$(
go.TextBlock,
"",
{
textAlign: "center",
font: "12pt helvetica, arial, sans-serif",
stroke: "#A1F9FA",
editable: true,
},
new go.Binding("text", "port1").makeTwoWay()
)
);
//在每条线中心添加小节点以便实现T接线方式
this.myDiagram.nodeTemplateMap.add(
"LinkLabel",
$(
"Node",
{
selectable: false,
avoidable: false,
layerName: "Foreground",
},
$("Shape", "Ellipse", {
width: 10,
height: 10,
stroke: null,
fill: null, //去掉小圆点
portId: "",
fromLinkable: true,
toLinkable: true,
cursor: "pointer",
})
)
);
// GraphLinkModel对链接标签节点的支持需要指定两个属性
// 优化连线
this.myDiagram.model = $(go.GraphLinksModel, {
linkLabelKeysProperty: "labelKeys",
});
// 每当通过链接工具绘制新链接时,它还添加节点数据对象。
// 用作链接的标签节点的,以允许向链接绘制链接或从链接绘制链接。
this.myDiagram.toolManager.linkingTool.archetypeLabelNodeData = {
category: "LinkLabel",
};
this.myDiagram.model = go.Model.fromJson(json);
//动画效果
// this.changeImg();
},
4、判断连线是否为小黑点(并不是节点,而是用于T接线的黑点)
maybeChangeLinkCategory(e) {
var link = e.subject;
var linktolink = link.fromNode.isLinkLabel || link.toNode.isLinkLabel;
//在线中判断是否连接小黑点用于个人业务逻辑
e.diagram.model.setCategoryForLinkData(
link.data,
linktolink ? "linkToLink" : ""
);
},
5、右键按钮事件封装成公共方法
//上下文button
makeButton(text, action, visiblePredicate) {
return $(
"ContextMenuButton",
$(go.TextBlock, text, {
alignment: go.Spot.Left,
margin: 5,
textAlign: "center",
font: "14px sans-serif",
opacity: 0.85,
stroke: "#404040",
width: 100,
}),
{ click: action },
// don't bother with binding GraphObject.visible if there's no predicate
visiblePredicate
? new go.Binding("visible", "", (o, e) =>
o.diagram ? visiblePredicate(o, e) : false
).ofObject()
: {}
);
},
6.对应的右键事件处理函数封装
// 添加头部小节点
addPort(side) {
this.myDiagram.startTransaction("addPort");
this.myDiagram.selection.each((node) => {
// skip any selected Links
if (!(node instanceof go.Node)) return;
// compute the next available index number for the side
let i = 0;
while (node.findPort(side + i.toString()) !== node) i++;
// now this new port name is unique within the whole Node because of the side prefix
const name = side + i.toString();
// get the Array of port data to be modified
const arr = node.data[side + "Array"];
if (arr) {
// create a new port data object
const newportdata = {
portId: name,
portColor: "#2e68cc",
};
// and add it to the Array of port data
this.myDiagram.model.insertArrayItem(arr, -1, newportdata);
}
});
this.myDiagram.commitTransaction("addPort");
},
// 删除小节点
removePort(port) {
this.myDiagram.startTransaction("removePort");
const pid = port.portId;
const arr = port.panel.itemArray;
for (let i = 0; i < arr.length; i++) {
if (arr[i].portId === pid) {
this.myDiagram.model.removeArrayItem(arr, i);
break;
}
}
this.myDiagram.commitTransaction("removePort");
},
// 删除全部小节点
removeAll(port) {
this.myDiagram.startTransaction("removePorts");
const nodedata = port.part.data;
const side = port._side; // there are four property names, all ending in "Array"
this.myDiagram.model.setDataProperty(nodedata, side + "Array", []); // an empty Array
this.myDiagram.commitTransaction("removePorts");
},
// 更改小节点颜色
changeColor(port) {
this.myDiagram.startTransaction("colorPort");
const data = port.data;
this.myDiagram.model.setDataProperty(data, "portColor", "#ddd");
this.myDiagram.commitTransaction("colorPort");
},
// 更改背景色
changeBackground(port) {
// this.myDiagram.startTransaction("colorPort");
const data = port.data;
this.myDiagram.model.setDataProperty(data, "source", error2);
// this.myDiagram.commitTransaction("colorPort");
},
7.动画效果的实现
AnimationYes() {
var animation = new go.Animation();
animation.easing = go.Animation.EaseLinear;
this.myDiagram.links.each(function (link) {
// 60 20
animation.add(link.findObject("DongHua"), "strokeDashOffset", 60, 20);
});
animation.runCount = Infinity;
animation.start();
},
模拟电流
更多推荐
已为社区贡献1条内容
所有评论(0)