项目这边的需求是绘制有一定关系的拓扑图,所以这里我决定使用gojs的UML class绘制。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="js/go.js"></script>
</head>
<body onload="init()">
<div id="sample">
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:800px"></div>
</div>
</body>
</html>
<script>
function init() {
if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
var $ = go.GraphObject.make;
myDiagram =
$(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center,
"undoManager.isEnabled": true,
layout: $(go.TreeLayout,
{ // this only lays out in trees nodes connected by "generalization" links
angle: 90,
path: go.TreeLayout.PathSource, // links go from child to parent
setsPortSpot: false, // keep Spot.AllSides for link connection spot
setsChildPortSpot: false, // keep Spot.AllSides
// nodes not connected by "generalization" links are laid out horizontally
arrangement: go.TreeLayout.ArrangementHorizontal
})
});
// show visibility or access as a single character at the beginning of each property or method
function convertVisibility(v) {
switch (v) {
case "public": return "+";
case "private": return "-";
case "protected": return "#";
case "package": return "~";
default: return v;
}
}
// the item template for properties
var propertyTemplate =
$(go.Panel, "Horizontal",
// property visibility/access
/* $(go.TextBlock,
{ isMultiline: false, editable: false, width: 12 },
new go.Binding("text", "visibility", convertVisibility)),*/
// property name, underlined if scope=="class" to indicate static property
$(go.TextBlock,
{ isMultiline: false, editable: true },
new go.Binding("text", "name").makeTwoWay(),
new go.Binding("isUnderline", "scope", function(s) { return s[0] === 'c' })),
// property type, if known
$(go.TextBlock, "",
new go.Binding("text", "type", function(t) { return (t ? ": " : ""); })),
$(go.TextBlock,
{ isMultiline: false, editable: true },
new go.Binding("text", "type").makeTwoWay()),
// property default value, if any
$(go.TextBlock,
{ isMultiline: false, editable: false },
new go.Binding("text", "default", function(s) { return s ? " = " + s : ""; }))
);
// the item template for methods
var methodTemplate =
$(go.Panel, "Horizontal",
// method visibility/access
/*$(go.TextBlock,
{ isMultiline: false, editable: false, width: 12 },
new go.Binding("text", "visibility", convertVisibility)),*/
// method name, underlined if scope=="class" to indicate static method
$(go.TextBlock,
{ isMultiline: false, editable: true },
new go.Binding("text", "name").makeTwoWay(),
new go.Binding("isUnderline", "scope", function(s) { return s[0] === 'c' })),
// method parameters
$(go.TextBlock, "()",
// this does not permit adding/editing/removing of parameters via inplace edits
new go.Binding("text", "parameters", function(parr) {
var s = "(";
for (var i = 0; i < parr.length; i++) {
var param = parr[i];
if (i > 0) s += ", ";
s += param.name + ": " + param.type;
}
return s + ")";
})),
// method return type, if any
$(go.TextBlock, "",
new go.Binding("text", "type", function(t) { return (t ? ": " : ""); })),
$(go.TextBlock,
{ isMultiline: false, editable: true },
new go.Binding("text", "type").makeTwoWay())
);
// this simple template does not have any buttons to permit adding or
// removing properties or methods, but it could!
myDiagram.nodeTemplate =
$(go.Node, "Auto",
{
locationSpot: go.Spot.Center,
fromSpot: go.Spot.AllSides,
toSpot: go.Spot.AllSides
},
$(go.Shape, { fill: "#dddddd" }),
$(go.Panel, "Table",
{ defaultRowSeparatorStroke: "black" },
// header
$(go.TextBlock,
{
row: 0, columnSpan: 2, margin: 3, alignment: go.Spot.Center,
font: "bold 12pt sans-serif",
isMultiline: false, editable: true
},
new go.Binding("text", "name").makeTwoWay()),
// properties
$(go.TextBlock, "Properties",
{ row: 1, font: "italic 10pt sans-serif" },
new go.Binding("visible", "visible", function(v) { return !v; }).ofObject("PROPERTIES")),
$(go.Panel, "Vertical", { name: "PROPERTIES" },
new go.Binding("itemArray", "properties"),
{
row: 1, padding: 5, stretch: go.GraphObject.Fill,
defaultAlignment: go.Spot.Left, background: "#ffffff",
itemTemplate: propertyTemplate
}
),
/*$("PanelExpanderButton", "PROPERTIES",
{ row: 1, column: 1, alignment: go.Spot.TopRight, visible: false },
new go.Binding("visible", "properties", function(arr) { return arr.length > 0; })),*/
// methods
$(go.TextBlock, "Methods",
{ row: 2, font: "italic 10pt sans-serif" },
new go.Binding("visible", "visible", function(v) { return !v; }).ofObject("METHODS")),
$(go.Panel, "Vertical", { name: "METHODS" },
new go.Binding("itemArray", "methods"),
{
row: 2, padding: 5, stretch: go.GraphObject.Fill,
defaultAlignment: go.Spot.Left, background: "#ffffff",
itemTemplate: methodTemplate
}
),
/* $("PanelExpanderButton", "METHODS",
{ row: 2, column: 1, alignment: go.Spot.TopRight, visible: false },
new go.Binding("visible", "methods", function(arr) { return arr.length > 0; }))*/
)
);
function convertIsTreeLink(r) {
return r === "generalization";
}
function convertFromArrow(r) {
switch (r) {
case "generalization": return "";
default: return "";
}
}
function convertToArrow(r) {
switch (r) {
case "generalization": return "";
case "aggregation": return "";
default: return "";
}
}
myDiagram.linkTemplate =
$(go.Link,
{ routing: go.Link.Orthogonal },
new go.Binding("isLayoutPositioned", "relationship", convertIsTreeLink),
$(go.Shape),
$(go.Shape, { scale: 1.3, fill: "white" },
new go.Binding("fromArrow", "relationship", convertFromArrow)),
$(go.Shape, { scale: 1.3, fill: "white" },
new go.Binding("toArrow", "relationship", convertToArrow)),
$(go.Panel, "Auto",
$(go.Shape, // the label background, which becomes transparent around the edges
{
fill: $(go.Brush, "Radial",
{ 0: "rgb(240, 240, 240)", 0.3: "rgb(240, 240, 240)", 1: "rgba(240, 240, 240, 0)" }),
stroke: null
}),
$(go.TextBlock, "transition", // the label text
{
textAlign: "center",
font: "9pt helvetica, arial, sans-serif",
margin: 4,
editable: true // enable in-place editing
},
// editing the text automatically updates the model data
new go.Binding("text").makeTwoWay())
)
);
// setup a few example class nodes and relationships
var nodedata = [
{
key: 1,
name: "BankAccount",
properties: [
{ name: "owner", type: "String"},
{ name: "balance", type: "Currency"}
],
methods: [
{ name: "deposit", parameters: [{ name: "amount", type: "Currency" }]},
{ name: "withdraw", parameters: [{ name: "amount", type: "Currency" }]}
]
},
{
key: 11,
name: "Person",
properties: [
{ name: "name", type: "String"},
{ name: "birth", type: "Date"}
],
methods: [
{ name: "getCurrentAge", type: "int"}
]
},
{
key: 12,
name: "Student",
properties: [
{ name: "classes", type: "List"}
],
methods: [
{ name: "attend", parameters: [{ name: "class", type: "Course" }]},
{ name: "sleep"}
]
},
{
key: 13,
name: "Professor",
properties: [
{ name: "classes", type: "List"}
],
methods: [
{ name: "teach", parameters: [{ name: "class", type: "Course" }]}
]
},
{
key: 14,
name: "Course",
properties: [
{ name: "name", type: "String"},
{ name: "description", type: "String"},
{ name: "professor", type: "Professor"},
{ name: "location", type: "String"},
{ name: "times", type: "List"},
{ name: "prerequisites", type: "List"},
{ name: "students", type: "List"}
],
methods: [
{ name: "teach", parameters: [{ name: "class", type: "Course" }]}
]
}
];
var linkdata = [
{ from: 1, to: 11, relationship: "generalization", text: "啦啦啦啦"},
{ from: 12, to: 11, relationship: "generalization", text: "啦啦啦啦"},
{ from: 13, to: 11, relationship: "generalization", text: "啦啦啦啦" },
{ from: 14, to: 13, relationship: "generalization", text: "啦啦啦啦" }
];
myDiagram.model = $(go.GraphLinksModel,
{
copiesArrays: true,
copiesArrayObjects: true,
nodeDataArray: nodedata,
linkDataArray: linkdata
});
}
</script>
运行后的效果图如下: