专栏名称: SegmentFault思否
SegmentFault (www.sf.gg)开发者社区,是中国年轻开发者喜爱的极客社区,我们为开发者提供最纯粹的技术交流和分享平台。
目录
相关文章推荐
程序员的那些事  ·  OpenAI ... ·  11 小时前  
OSC开源社区  ·  升级到Svelte ... ·  3 天前  
程序员的那些事  ·  惊!小偷“零元购”后竟向 DeepSeek ... ·  2 天前  
程序员的那些事  ·  成人玩偶 + ... ·  3 天前  
51好读  ›  专栏  ›  SegmentFault思否

关于 GoJS 你了解多少?

SegmentFault思否  · 公众号  · 程序员  · 2019-11-29 14:22

正文

本文原载于 SegmentFault 社区专栏:木易杨@

作者:yang




GoJS 是用于实现交互式图的 JavaScript 库。
GoJS 是依赖 HTML5 功能的 JavaScript 库。



使用



<!DOCTYPE html> <!-HTML5文档类型->
< html >
< head >
<!-开发时使用go-debug.js,部署时使用go.js->
< script src = go-debug .js“ > script >
直接链接到 CDN 提供的 GoJS 库:

<script src="https://cdnjs.cloudflare.com/ajax/libs/gojs/1.7.8/go-debug.js">script>

每个 GoJS 图表都包含在
您的 HTML 页面的 HTML 元素中,您可以提供明确的大小:

在这种情况下,我们还添加了背景色,以便我们可以看到该区域。->
< div id = “ myDiagramDiv”
style = “ width400px; height150px; background-color:#DAE4E4;” > div >
在 JavaScript 代码您传递
的 id 制作图表时:

var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram,“ myDiagramDiv”);


注意,这 go 是所有 GoJS 类型所在的“名称空间”。GoJS 类的所有代码用法 (例如图或节点或面板或 Shape 或 TextBlock) 都将以 “go.” 作为前缀。

本文将通过示例向您展示如何 go.GraphObject.make 用于构建 GoJS 对象。有关更多详细信息,请阅读
GoJS 中的 Building Objects

使用 $ 作为一个缩写,go.GraphObject.make 是那么得心应手,我们将假设从现在开始使用它。如果你使用 $ 你的代码别的东西,你总是可以选择一个不同的短变量名称,如 $$ 或 MAKE 或 GO。




图表和模型



图的节点和链接是由模型管理的数据的可视化。GoJS 具有模型视图架构,其中模型保存描述节点和链接的数据 (JavaScript 对象的数组) ,而图作为视图使用实际的 Node 和 Link 对象可视化此数据。在编辑后加载然后保存的是模型而不是图。您可以在模型的数据对象上添加应用所需的任何属性;您不向 Diagram 和 GraphObject 类添加属性或修改其原型。

这是一个模型和图的示例,后面是它生成的实际图:

var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram,“ myDiagramDiv”,
{ “ undoManager.isEnabled”:true //启用Ctrl-Z撤消和Ctrl-Y重做
}); var myModel = $(go.Model);
//在模型数据中,每个节点都由一个JavaScript对象表示:
myModel.nodeDataArray = [
{ key:“ Alpha” },
{ key:“ Beta” },
{ key:“ Gamma” }
];
myDiagram.model = myModel;

显示了模型中的三个节点。已经可以进行一些交互:

* 单击并拖动上图中的背景以平移视图。
* 单击一个节点以将其选中,或者按下并拖动一个节点以将其移动。
* 要创建选择框,请单击并按住背景,然后开始拖动。
* 使用CTRL-C和CTRL-V或按住Control并拖放来制作所选内容的副本。
* 按Delete键删除选定的节点。(了解有关更多[键盘命令的信息](https://gojs.net/latest/intro/commands.html)。)
* 由于启用了撤消管理器,因此CTRL-Z和CTRL-Y将撤消和重做移动以及复制和删除操作。



样式节点



通过创建由 GraphObject 组成的模板并在这些对象上设置属性来设置节点的样式。要创建 Node ,我们可以使用几个构建基块类:

•  Shape ,以显示带有颜色的预定义或自定义几何
TextBlock,以显示各种字体的文本 (可能可编辑)
图片 ,显示图像
Panel,用于容纳其他对象集合的容器,这些对象可以根据 Panel 的类型以不同的方式放置和调整大小 (例如桌子,垂直堆栈和拉伸容器)

所有这些构建块均来自 GraphObject 抽象类,因此我们随便将它们称为 GraphObjects 或对象或元素。请注意,GraphObject_ 不是 _HTML DOM 元素,因此在创建或修改此类对象时没有太多开销。

我们希望模型数据属性影响我们的节点,这是通过数据绑定来完成的。数据绑定使我们可以通过将 GraphObject 上的属性自动设置为从模型数据中获取的值来更改 GraphObject 在 Nodes 中的外观和行为。模型数据对象是普通的 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"))
);
TextBlocks,Shape 和 Pictures 是 GoJS 的原始构建块。TextBlocks 不能包含图像。形状不能包含文本。如果要让节点显示一些文本,则必须使用 TextBlock。如果要绘制或填充一些几何图形,则必须使用“形状”。

更一般地,Node 模板的框架看起来像这样:

myDiagram.nodeTemplate =
$(go.Node, "Vertical", //节点/面板的第二个参数可以是面板类型
/ *在此处设置节点属性* /
{ // Node.location点将位于每个节点
locationSpot: go.Spot.Center
},

/ *在此处添加绑定* / //示例节点绑定将Node.location设置为Node.data.loc的值
new go.Binding("location", "loc"),

/ *添加包含在Node中的GraphObjects * / //此Shape将垂直位于TextBlock
$(go.Shape,
"RoundedRectangle", //字符串参数可以命名预定义的图形
{ / *在这里设置Shape属性* / },
//示例Shape绑定将Shape.figure设置为Node.data.fig的值
new go.Binding("figure", "fig")),

$(go.TextBlock,
"default text", //字符串参数可以是初始文本字符串
{ / *在这里设置TextBlock属性* / },
//示例TextBlock绑定将TextBlock.text设置为Node.data的值.key
new go.Binding("text", "key"))
);

Panel 中 GraphObjects 的嵌套可以任意深,每个类都有其自己独特的属性集可进行探索,但这表明了基本思想。

既然我们已经了解了如何制作 Node 模板,那么让我们来看一个实时示例。我们将制作一个在组织结构图中常见的简单模板-名称旁边的图像。考虑以下节点模板:

•  一个“水平”面板类型的节点,表示其元素将水平并排放置。它包含两个元素:


肖像的图片,已绑定图像源数据
名称的 TextBlock,绑定了文本数据
var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram,“ myDiagramDiv”,
{ “ undoManager.isEnabled”:true //启用Ctrl-Z撤消和Ctrl-Y重做
}); //定义一个简单的Node模板
myDiagram.nodeTemplate =
$(go.Node,“ Horizontal”,
//整个节点将具有浅蓝色背景
{ background:“#44CCFF” },
$(go.Picture,//图片通常应具有明确的宽度和高度//此图片具有红色背景,仅在未设置源的情况下可见





//或图像部分透明时。
{ margin:10,width:50,height:50,background:“ red” },
// Picture.source是绑定到模型数据的“ source”属性的数据
new go.Binding(“ source”))),
$ (go.TextBlock,“ Default Text”, // TextBlock.text的初始值//文本周围有一些空间,一个较大的字体和一个白色笔画:
{ margin:12,stroke:

“ white”,font:“ bold 16px sans-serif” },
// TextBlock.text是绑定到模型数据的name属性的数据
new go.Binding(“ text”,“ name”))
)); var model = $(go.Model);
model.nodeDataArray =
[ //注意,每个节点数据对象都拥有所需的任何属性;//为此应用程序,我们添加了“ name”和“ source”属性
{ name:“ Don Meow”,source:“ cat1.png” },
{ name:


:“” cat2.png“ },
{ name:” Demeter“, source:” cat3.png“ },
{ / *空节点数据* / }
];
myDiagram.model =model;
当并非所有信息都存在时,例如当图像未加载或名称未知时,我们可能希望显示一些“默认”状态。此示例中的“空”节点数据用于显示节点模板可以很好地工作,而无需绑定数据上的任何属性。



型号种类



使用自定义节点模板,我们的图变得很漂亮,但是也许我们想展示更多。 也许我们希望组织结构图显示 Don Meow 确实是卡特尔的老板。 因此,我们将通过添加一些链接以显示各个节点之间的关系以及一个自动放置节点的布局来创建完整的组织结构图。

为了使链接进入我们的图表,基本 Model 不会删除它。我们将不得不在 GoJS 中选择其他两个模型之一,它们都支持 Links。这些是 GraphLinksModel 和 TreeModel。

在 GraphLinksModel中,model.linkDataArray 除了 model.nodeDataArray。 它包含一个 JavaScript 对象数组,每个 JavaScript 对象都通过指定“ to”和“ from”节点键来描述链接。 这是一个示例,其中节点 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;

TreeModel 比 GraphLinksModel 简单,但是它不能建立任意的链接关系,例如同一两个节点之间的多个链接或具有多个父级。 我们的组织结构图是一个简单的分层树状结构,因此在此示例中将选择 TreeModel。

首先,我们将通过使用 TreeModel 添加更多的节点并在数据中指定键和父级来完成数据。

var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram, "myDiagramDiv",
{
"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 自动创建必要的 Links 来关联 Node,但是很难确定谁是谁。

图具有默认布局,该布局采用所有没有位置的节点并将其分配给它们,然后将它们排列在网格中。 我们可以显式地为每个节点提供一个位置,以解决这种组织混乱的情况,但是,在我们的案例中,作为一种更简单的解决方案,我们将使用一种布局,该布局可以自动为我们提供良好的位置。

我们想要显示一个层次结构,并且已经在使用 TreeModel,因此最自然的布局选择是 TreeLayout。TreeLayout 默认为从左到右流动,因此要使其从上到下流动 (这在组织图中是常见的) ,我们将 angle 属性设置为 90。

在 GoJS 中使用布局通常很简单。每种布局都有许多影响结果的属性。每个布局都有一些示例 (例如 TreeLayout Demo) 来展示其属性。

//定义从上到下流动的 
TreeLayout myDiagram.layout =
$(go.TreeLayout,
{ angle90,layerSpacing:35 });

到目前为止,将布局添加到图和模型中,我们可以看到结果:

var $ = go.GraphObject.make;
var myDiagram =
$(go.Diagram, "myDiagramDiv",
{
"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;

我们的图表开始看起来像是正确的组织结构图,但是我们可以通过链接做得更好。








请到「今天看啥」查看全文