GoJS是一个用于实现交互式图表的JavaScript库。本页将向您介绍使用GoJS的基本知识。
由于GoJS是一个依赖于HTML5功能的JavaScript库,因此您需要确保您的网页声明它是一个HTML5文档。当然,你需要加载库:
<!DOCTYPE html> <!-- HTML5 document type -->
<html>
<head>
<!-- use go-debug.js when developing and go.js when deploying -->
<script src="go-debug.js"></script>
. . .
你可以在这里下载GoJS(和所有的样品)。另外,您可以直接链接到GoJS所提供的库CDNJS:
<script src="https://cdnjs.cloudflare.com/ajax/libs/gojs/1.7.3/go-debug.js"></script>
每个GoJS图都包含在<div>
HTML页面中的HTML 元素中,您可以指定明确的大小:
<!-- The DIV for a Diagram needs an explicit size or else we will not see anything.
In this case we also add a background color so we can see that area. -->
<div id="myDiagramDiv"
style="width:400px; height:150px; background-color: #DAE4E4;"></div>
在JavaScript代码,你传递<div>
的id
制作图表时:
var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram, "myDiagramDiv");
一起,这创建一个空图:
注意,这go
是所有GoJS类型驻留的“命名空间” 。所有代码使用的GoJS类,如图或节点或面板或形状或TextBlock将以“ go.
” 为前缀。
本文将通过示例演示如何使用go.GraphObject.make
构建GoJS对象。有关更多详细信息,请参阅GoJS中的构建对象。使用$
作为缩写go.GraphObject.make
是如此方便,我们将假设它的使用从现在开始。如果你$
在代码中使用别的东西,你总是可以选择一个不同的短变量名,例如$$
or MAKE
或GO
。
图和模型
图的节点和链接是由模型管理的数据的可视化。 GoJS有一个模型视图体系结构,其中模型保存描述节点和链接的数据(JavaScript对象数组),图表用作视图,使用实际的Node和Link对象可视化这些数据。模型,而不是图,是您加载,然后编辑后保存。您可以在模型中的数据对象上添加应用程序所需的任何属性; 您不需要添加属性或修改Diagram和GraphObject类的原型。
下面是一个模型和图的示例,其后是它生成的实际图:
var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center, // center Diagram contents
"undoManager.isEnabled": true // enable Ctrl-Z to undo and Ctrl-Y to redo
});
var myModel = $(go.Model);
// in the model data, each node is represented by a JavaScript object:
myModel.nodeDataArray = [
{ key: "Alpha" },
{ key: "Beta" },
{ key: "Gamma" }
];
myDiagram.model = myModel;
该图显示模型中的三个节点。一些互动已经可能:
- 单击并拖动上图中的背景以平移视图。
- 单击节点以将其选中,或者向下按并拖动节点以将其移动。
- 要创建选择框,请单击并按住背景,然后开始拖动。
- 使用CTRL-C和CTRL-V或控制拖放,制作选择的副本。
- 按Delete键删除所选节点。(了解更多键盘命令。)
- 由于undo管理器被启用,CTRL-Z和CTRL-Y将撤消和重做移动,副本和删除。
样式节点
通过创建由GraphObject组成的模板并在这些对象上设置属性来对节点进行样式化。为了创建一个Node,我们有几个构造块类:
- 形状,用颜色显示预定义或自定义几何
- TextBlock,以各种字体显示(可能可编辑)文本
- 图片,显示图像
- 面板,容器,用于容纳可根据面板类型以不同方式定位和定尺寸的其他对象的集合(如桌子,垂直堆叠和拉伸容器)
所有这些构建块都是从 GraphObject抽象类派生的,所以我们随便将它们称为GraphObjects或对象或元素。请注意,GraphObject 不是 HTML DOM元素,因此在创建或修改此类对象时没有太多的开销。
我们希望模型数据属性影响我们的节点,这是通过数据绑定完成的。数据绑定允许我们通过将这些GraphObject上的属性自动设置为从模型数据中提取的值来更改Nodes中GraphObject的外观和行为。模型数据对象是纯JavaScript对象。您可以选择在模型中的节点数据上使用任何您喜欢的属性名称。
默认的Node模板很简单:一个包含一个TextBlock的Node。在TextBlock的text
属性和模型数据的key
属性之间有一个数据绑定。在代码中,模板看起来像这样:
myDiagram.nodeTemplate =
$(go.Node,
$(go.TextBlock,
// TextBlock.text is bound to Node.data.key
new go.Binding("text", "key"))
);
注意没有Node.key
属性。但你可以得到一个节点通过的密钥someNode.data.key
。
的TextBlocks,形状,和图片的原始积木GoJS。TextBlocks不能包含图像; 形状不能包含文本。如果希望您的节点显示一些文本,则必须使用TextBlock。如果要绘制或填充某些几何图形,则必须使用形状。
更一般地,Node模板的框架将如下所示:
myDiagram.nodeTemplate =
$(go.Node, "Vertical" // second argument of a Node/Panel can be a Panel type
/* set Node properties here */
{ // the Node.location point will be at the center of each node
locationSpot: go.Spot.Center
},
/* add Bindings here */
// example Node binding sets Node.location to the value of Node.data.loc
new go.Binding("location", "loc"),
/* add GraphObjects contained within the Node */
// this Shape will be vertically above the TextBlock
$(go.Shape,
"RoundedRectangle", // string argument can name a predefined figure
{ /* set Shape properties here */ },
// example Shape binding sets Shape.figure to the value of Node.data.fig
new go.Binding("figure", "fig")),
$(go.TextBlock,
"default text", // string argument can be initial text string
{ /* set TextBlock properties here */ },
// example TextBlock binding sets TextBlock.text to the value of Node.data.key
new go.Binding("text", "key"))
);
面板中的GraphObjects的嵌套可以任意深,每个类都有自己独特的属性集来探索,但这显示了一般的想法。
现在我们已经看到了如何创建一个Node模板,让我们看一个实例。我们将创建一个在组织图中常见的简单模板 - 名称旁边的图像。考虑以下Node模板:
- “水平”面板类型的节点,表示其元素将水平并排布置。它有两个元素:
- 用于肖像的图片,带有图像源数据
- 一个TextBlock的名称,与文本数据绑定
var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center, // center Diagram contents
"undoManager.isEnabled": true // enable Ctrl-Z to undo and Ctrl-Y to redo
});
// define a simple Node template
myDiagram.nodeTemplate =
$(go.Node, "Horizontal",
// the entire node will have a light-blue background
{ background: "#44CCFF" },
$(go.Picture,
// Pictures should normally have an explicit width and height.
// This picture has a red background, only visible when there is no source set
// or when the image is partially transparent.
{ margin: 10, width: 50, height: 50, background: "red" },
// Picture.source is data bound to the "source" attribute of the model data
new go.Binding("source")),
$(go.TextBlock,
"Default Text", // the initial value for TextBlock.text
// some room around the text, a larger font, and a white stroke:
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
// TextBlock.text is data bound to the "name" attribute of the model data
new go.Binding("text", "name"))
);
var model = $(go.Model);
model.nodeDataArray =
[ // note that each node data object holds whatever properties it needs;
// for this app we add the "name" and "source" properties
{ name: "Don Meow", source: "cat1.png" },
{ name: "Copricat", source: "cat2.png" },
{ name: "Demeter", source: "cat3.png" },
{ /* Empty node data */ }
];
myDiagram.model = model;
该代码生成此图:
当不是所有信息都存在时,我们可能想要显示一些“默认”状态,例如当图像不加载或者不知道名称时。在此示例中,“空”节点数据用于显示节点模板可以很好地工作,而没有绑定数据上的任何属性。
种类的模型
使用自定义节点模板我们的图表变得很漂亮,但也许我们想要显示更多。也许我们想要一个组织图表显示唐喵真的是猫卡特尔的老板。因此,我们将通过添加一些链接来显示单个节点之间的关系并创建一个布局来自动定位节点,从而创建一个完整的组织图表图表。
为了链接到我们的图,基本Model
是不会削减它。我们将要选择GoJS中的其他两个模型之一,这两个模型都支持Links。这些是GraphLinksModel
和TreeModel
。(更多关于模型的信息。)
在GraphLinksModel中,我们model.linkDataArray
除了model.nodeDataArray
。它拥有一个JavaScript对象数组,每个对象通过指定“到”和“从”节点键来描述链接。这里有一个例子,其中节点A链接到节点B,而节点B链接到节点C:
var model = $(go.GraphLinksModel);
model.nodeDataArray =
[
{ key: "A" },
{ key: "B" },
{ key: "C" }
];
model.linkDataArray =
[
{ from: "A", to: "B" },
{ from: "B", to: "C" }
];
myDiagram.model = model;
GraphLinksModel允许你在任何方向上在节点之间有任意数量的链接。可以有从A到B运行的十个链接,另外三个运行从B到A的相反方向。
TreeModel的工作方式略有不同。代替维护单独的链接数据阵列,通过为节点数据指定“父”来创建树模型中的链接。然后从此关联创建链接。下面是与TreeModel相同的示例,其中节点A链接到节点B,节点B链接到节点C:
var model = $(go.TreeModel);
model.nodeDataArray =
[
{ key: "A" },
{ key: "B", parent: "A" },
{ key: "C", parent: "B" }
];
myDiagram.model = model;
TreeModel比GraphLinksModel更简单,但它不能制作任意的链接关系,如同一两个节点之间的多个链接,或有多个父节点。我们的组织图是一个简单的分层树状结构,所以我们将为这个例子选择TreeModel。
首先,我们将通过添加几个节点来完成数据,使用TreeModel,并在数据中指定键和父对象。
var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center, // center Diagram contents
"undoManager.isEnabled": true // enable Ctrl-Z to undo and Ctrl-Y to redo
});
// the template we defined earlier
myDiagram.nodeTemplate =
$(go.Node, "Horizontal",
{ background: "#44CCFF" },
$(go.Picture,
{ margin: 10, width: 50, height: 50, background: "red" },
new go.Binding("source")),
$(go.TextBlock, "Default Text",
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
new go.Binding("text", "name"))
);
var model = $(go.TreeModel);
model.nodeDataArray =
[ // the "key" and "parent" property names are required,
// but you can add whatever data properties you need for your app
{ key: "1", name: "Don Meow", source: "cat1.png" },
{ key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
{ key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
{ key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
{ key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
{ key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
];
myDiagram.model = model;
图布局
正如你可以看到的TreeModel自动创建必要的链接来关联节点,但很难知道谁的父亲是谁。
图表具有默认布局,它采用没有位置的所有节点,并给它们位置,将它们排列在网格中。我们可以显式地给每个节点一个位置来整理这个组织的混乱,但作为一个更容易的解决方案,在我们的情况下,我们将使用一个布局,自动给我们良好的位置。
我们想要显示一个层次结构,并且已经在使用TreeModel,所以最自然的布局选择是TreeLayout。TreeLayout默认从左到右流动,所以为了让它从上到下流动(在组织图中是常见的),我们将angle
属性设置为90。
在GoJS中使用布局通常很简单。每种布局都有一些影响结果的属性。有每个布局(如TreeLayout演示)的样品展示其属性。
// define a TreeLayout that flows from top to bottom
myDiagram.layout =
$(go.TreeLayout,
{ angle: 90, layerSpacing: 35 });
GoJS有其他几个布局,你可以在这里阅读。
到目前为止,将布局添加到图表和模型中,我们可以看到我们的结果:
var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center, // center Diagram contents
"undoManager.isEnabled": true, // enable Ctrl-Z to undo and Ctrl-Y to redo
layout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees
{ angle: 90, layerSpacing: 35 })
});
// the template we defined earlier
myDiagram.nodeTemplate =
$(go.Node, "Horizontal",
{ background: "#44CCFF" },
$(go.Picture,
{ margin: 10, width: 50, height: 50, background: "red" },
new go.Binding("source")),
$(go.TextBlock, "Default Text",
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
new go.Binding("text", "name"))
);
var model = $(go.TreeModel);
model.nodeDataArray =
[
{ key: "1", name: "Don Meow", source: "cat1.png" },
{ key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
{ key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
{ key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
{ key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
{ key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
];
myDiagram.model = model;
我们的图表开始看起来像一个正确的组织图,但我们可以做得更好的链接。
链接模板
我们将构建一个新的链接模板,以更好地适合我们的宽泛的节点。一个链接是一种不同的部分,并不像是一个节点。链接的主要元素是链接的形状,并且必须是具有由GoJS动态计算的几何形状的形状。我们的链接将包括这个形状,它的笔画比正常的一点厚,深灰色而不是黑色。与默认链接模板不同,我们不会有一个箭头。我们将链接routing
属性从正常更改为正交,并给它一个corner
值,以使直角匝被四舍五入。
// define a Link template that routes orthogonally, with no arrowhead
myDiagram.linkTemplate =
$(go.Link,
// default routing is go.Link.Normal
// default corner is 0
{ routing: go.Link.Orthogonal, corner: 5 },
$(go.Shape, { strokeWidth: 3, stroke: "#555" }) // the link shape
// if we wanted an arrowhead we would also add another Shape with toArrow defined:
// $(go.Shape, { toArrow: "Standard", stroke: null }
);
结合我们的链接模板与我们的Node模板,TreeModel和TreeLayout,我们终于有了一个完整的组织图。完整的代码在下面重复,结果图如下:
var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram, "myDiagramDiv",
{
initialContentAlignment: go.Spot.Center, // center Diagram contents
"undoManager.isEnabled": true, // enable Ctrl-Z to undo and Ctrl-Y to redo
layout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees
{ angle: 90, layerSpacing: 35 })
});
// the template we defined earlier
myDiagram.nodeTemplate =
$(go.Node, "Horizontal",
{ background: "#44CCFF" },
$(go.Picture,
{ margin: 10, width: 50, height: 50, background: "red" },
new go.Binding("source")),
$(go.TextBlock, "Default Text",
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
new go.Binding("text", "name"))
);
// define a Link template that routes orthogonally, with no arrowhead
myDiagram.linkTemplate =
$(go.Link,
{ routing: go.Link.Orthogonal, corner: 5 },
$(go.Shape, { strokeWidth: 3, stroke: "#555" })); // the link shape
var model = $(go.TreeModel);
model.nodeDataArray =
[
{ key: "1", name: "Don Meow", source: "cat1.png" },
{ key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
{ key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
{ key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
{ key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
{ key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
];
myDiagram.model = model;
现在,您已经熟悉GoJS的一些基础知识,可以考虑仔细阅读示例以查看GoJS可能的一些图表,或阅读技术介绍以深入了解GoJS的组件。