转载:https://www.jianshu.com/p/9001d6b292d8
原文在这里:Get Started with GoJS
GoJS 是一个实现交互式图表(Diagram)的Javascript 库。这个页面展示了使用GoJS的精髓。因为GoJS是一个依赖于HTML5特性的Javascript库,所以你要搞清楚浏览器是否支持HTML5,当然首先要加载这个库:
<html>
<head><script src&#61;"go-debug.js">script>
你可以在这里下载,也可以直接引用这个地址CDN:
<script src&#61;"https://cdnjs.cloudflare.com/ajax/libs/gojs/1.7.2/go-debug.js">script>
每个GoJS图表包含在一个页面中固定尺寸的HTML
<div id&#61;"myDiagramDiv"style&#61;"width:400px; height:150px; background-color: #DAE4E4;">div>
在Javascript代码中你可以传递
var $ &#61; go.GraphObject.make;
var myDiagram &#61;$(go.Diagram, "myDiagramDiv");
这样就会获得一个空白的图表(Diagram):
记住GoJS的命名空间是 go&#xff0c;所有的GOJs包含的类型都在go这个命名空间下。所有的GoJS的类比如Diagram 、Node 、 Panel 、 Shape 、 TextBlock 都是以go.为前缀的。
这篇文章会举例告诉你如何调用go.GraphObject.make来创建一个GoJS对象。更详细的介绍情况请看 Building Objects in GoJS&#xff0c;它使用$作为go.GraphObject.make的缩写&#xff0c;这样很方便。如果你的代码中$表示别的对象&#xff0c;你也可以选一个其它的短变量&#xff0c;比如$$或者MAKE或者GO.
图表和模型图表(Diagram)的节点(Node)和链接(Link)是模型管理下的可视数据。GoJS支持模型-视图构架&#xff0c;当模型包含描述节点和链接的数据&#xff08;Javascript的数组对象&#xff09;。而且图表使用视图的方式来表现数据中的节点和链接对象。我们加载、编辑、保存的是模型而不是图表。你在模型的数据对象中添加你的APP需要的属性&#xff0c;而不是去修改Diagram 和GraphObject 类的原型。
下面是一个模型和图表(Diagram)的例子&#xff0c;再下面就是这个例子生成的图&#xff1a;
var $ &#61; go.GraphObject.make;
var myDiagram &#61;$(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 &#61; $(go.Model);
// in the model data, each node is represented by a Javascript object:
myModel.nodeDataArray &#61; [{ key: "Alpha" },{ key: "Beta" },{ key: "Gamma" }
];
myDiagram.model &#61; myModel;
图表(Diagram)展示了模型的三个节点。也能够实现一些交互&#xff1a;
节点的风格是由GraphObjects的模板和对象的属性值决定的&#xff0c;为了创建一个节点( Node),我们有一些构建形状块(building block)的类&#xff1a;
Shape, 显示预定义或者定制的带颜色的几何图形.
TextBlock, to display (potentially editable) text in various fonts
Picture, 显示图片
Panel,一个包含了其它的对象集合的容器&#xff0c;可以根据Panel的类型修改位置、尺寸.
所有的构建形状块(building block)都是从GraphObject 这个抽象类继承过来的, 所以我们可以随意的以GraphObjects 的方式引用他们。注意GraphObjects 不是一个HTML DOM 元素&#xff0c;所以不需要创建或者修改此类元素。
我们想通过模型数据的属性来影响节点&#xff0c;且这个是通过数据绑定来实现的。数据绑定允许我们修改节点上的GraphObjects的属性来修改 的外观和行为。模型对象是Javascript对象。你可以选择任意你想用的属性名来定义模型。缺省的节点模板是非常简单的&#xff0c;一个节点包含一个TextBlock类.TextBlock的Text属性和模型的key要绑定到一起&#xff0c;就像这样的代码&#xff1a;
The default Node template is simple: A Node which contains one TextBlock. There is a data binding
myDiagram.nodeTemplate &#61;$(go.Node,$(go.TextBlock,// TextBlock.text is bound to Node.data.keynew go.Binding("text", "key")));
注意没有Node.key的属性。但是你可以通过someNode.data.key来获取Node的key值。
TextBlocks,Shapes和Pictures是GoJS的原始的构建形状块。TextBlocks不能包含图片&#xff0c;Shapes不能包含文字。如果你想要节点显示文字&#xff0c;必须用TextBlock。如果你想画或者填充一些几何图形&#xff0c;你必须使用Shape.
一般情况下&#xff0c;节点的模块代码就像下面这个样子&#xff1a;
myDiagram.nodeTemplate &#61;$(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 nodelocationSpot: go.Spot.Center},/* add Bindings here */// example Node binding sets Node.location to the value of Node.data.locnew 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.fignew 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.keynew go.Binding("text", "key")));
Panels里面的GraphObjects 可以附着在任意的深度&#xff0c;而去每个类有他自己独有的属性&#xff0c;但是这里展示的是一般情况。
现在我们已经看了如果创建一个节点模板&#xff0c;让我们看一个实际的例子。我梦将会创建一个简单的组织架构图-节点包含名字和图片。考虑下如下的节点模板&#xff1a;
一个"水平"类型的节点&#xff0c;意思是节点中的元素将会水平并排放置&#xff0c;它有两个元素&#xff1a;
一个Picture对象表示照片&#xff0c;包含一个图片源数据的绑定
一个TextBlock对象表示名字&#xff0c;包含文字数据的绑定
var $ &#61; go.GraphObject.make;
var myDiagram &#61;$(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 &#61;$(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 datanew 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 datanew go.Binding("text", "name")));var model &#61; $(go.Model);
model.nodeDataArray &#61;
[ // 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 &#61; model;
以上的代码产生了下面这个图表&#xff1a;
当不是所有的信息都被完全展示时&#xff0c;我们可能会想显示一些缺省的的状态&#xff1a;比如图片没有下载完或者还不知道名字的时候。例子中空节点的数据就可以作为占位符。
模型的种类包含自定义模板的图表是非常漂亮的&#xff0c;但是或许我们想展示更多。比如我们想展示一个组织架构图&#xff0c;Don Meow的确是这个组织的老板。因此我们会创建一个完整的组织结构图&#xff0c;图中会在节点之间加上一些链接来展示人物关系&#xff0c;并且包含一个图层来自动排列节点。
为了把链接加入图中&#xff0c;基础的模型是不够用的。我们将会加入GoJS中的两个其它的模型。他们是GraphLinksModel和 TreeModel。
. (想要了解更多看 这里.)
在GraphLinksModel中, 我们除了model.nodeDataArray还有 model.linkDataArray。他包含了一个Javascript 对象数组&#xff0c;每个数组表示一个指定了“from”和“to”的链接的节点key。这是一个例子表示节点A链接到节点B以及节点B链接到节点C:
var model &#61; $(go.GraphLinksModel);
model.nodeDataArray &#61;
[{ key: "A" },{ key: "B" },{ key: "C" }
];
model.linkDataArray &#61;
[{ from: "A", to: "B" },{ from: "B", to: "C" }
];
myDiagram.model &#61; model;
一个GraphLinksModel 允许你任意个节点间的链接&#xff0c;包含任意的方向。可以有十个A到B的链接&#xff0c;和三个相反的B到A的链接。
一个TreeModel和GraphLinksModel有点不同。他并不包含一个链接数据的数组&#xff0c;而是创建了一个节点数据“父节点”的模型。链接用这种方式创建。下面是一个TreeModel的例子&#xff0c;包含一个节点A链接到B&#xff0c;B链接到C:
var model &#61; $(go.TreeModel);
model.nodeDataArray &#61;
[{ key: "A" },{ key: "B", parent: "A" },{ key: "C", parent: "B" }
];
myDiagram.model &#61; model;
TreeModel比 GraphLinksModel简单,但是他不能随意创建链接关系&#xff0c;比如不能在两个节点间创建的多个链接&#xff0c;也不能有多个父节点。我们的组织架构图是简单树形层级结构&#xff0c;所以我们选择TreeModel来实现这个例子&#xff1a;
首先&#xff0c;我们添加 几个节点&#xff0c;然后用TreeModel来指定key和父节点&#xff1a;
var $ &#61; go.GraphObject.make;
var myDiagram &#61;$(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 &#61;$(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 &#61; $(go.TreeModel);
model.nodeDataArray &#61;
[ // 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 &#61; model;
正如你可以看到的&#xff0c;TreeModel自动创建需要的节点间的链接&#xff0c;但是它很难确定谁的父节点是谁。
图表(Diagram)有一个缺省布局会管理那些没有具体位置的节点&#xff0c;会自动分配一个位置。我们可以显示的给每个节点分配一个位置来给组织排序&#xff0c;但是在我们的例子中一个更容易的解决方案是&#xff0c;我们会使用布局来自动排列位置。
我们想要来显示一个层级&#xff0c;而且已经用了TreeModel&#xff0c;因此最自然的方式是使用TreeLayout。TreeLayout缺省的是从左到右&#xff0c;因此为了表示从上到下的我们会将angle属性设置为90.
在GoJS中使用布局通常很简单。每种类型的布局有一些属性能影响结果。每种布局都是有例子的&#xff1a;(比如TreeLayout Demo)
// define a TreeLayout that flows from top to bottom
myDiagram.layout &#61;$(go.TreeLayout,{ angle: 90, layerSpacing: 35 });
GoJS 有许多其它的布局&#xff0c;你可以看 这里.
给图表添加布局&#xff0c;我们可以看到如下结果&#xff1a;
var $ &#61; go.GraphObject.make;
var myDiagram &#61;$(go.Diagram, "myDiagramDiv",{initialContentAlignment: go.Spot.Center, // center Diagram contents"undoManager.isEnabled": true, // enable Ctrl-Z to undo and Ctrl-Y to redolayout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees{ angle: 90, layerSpacing: 35 })});// the template we defined earlier
myDiagram.nodeTemplate &#61;$(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 &#61; $(go.TreeModel);
model.nodeDataArray &#61;
[{ 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 &#61; model;
这个图表看起来像是组织机构那么回事&#xff0c;但是我们可以做得更好。
链接模板(Link templates)我们会构建一个新的链接模板&#xff08;link template&#xff09;&#xff0c;这个模板可以更好的适应我们的宽的盒状的节点。链接Link是一个不同于Node的部分。链接主要的元素是链接的形状&#xff0c;而且必须是一个由 GoJS动态计算出来的形状。我们的链接是将会包含形状形状、比一般黑色的更宽一点的灰色笔画。不像缺省的链接模板&#xff0c;我们不会有箭头。而且我们会将Link routing 属性从Normal修改为Orthogonal&#xff0c;而且给他一个拐角值因此角会变园。
// define a Link template that routes orthogonally, with no arrowhead
myDiagram.linkTemplate &#61;$(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 });
综合我们的链接模板、节点模板、TreeModel和Treelayou&#xff0c;我们最终得到了一个完整的组织架构图。完整的代码在下面&#xff0c;紧跟的是生成的结果图&#xff1a;
var $ &#61; go.GraphObject.make;var myDiagram &#61;$(go.Diagram, "myDiagramDiv",{initialContentAlignment: go.Spot.Center, // center Diagram contents"undoManager.isEnabled": true, // enable Ctrl-Z to undo and Ctrl-Y to redolayout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees{ angle: 90, layerSpacing: 35 })});// the template we defined earlier
myDiagram.nodeTemplate &#61;$(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 &#61;$(go.Link,{ routing: go.Link.Orthogonal, corner: 5 },$(go.Shape, { strokeWidth: 3, stroke: "#555" })); // the link shapevar model &#61; $(go.TreeModel);
model.nodeDataArray &#61;
[{ 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 &#61; model;