js插件---在线mindmap实现方案(gojs)
一、总结
一句话总结:稍微花点时间看看文档,超级简单的
文档地址:https://gojs.net/latest/intro/index.html
1、mind map js插件如何搜索?
mind map js
这些都是很好的关键词
多使用google,google搜索比百度搜索好用多了,不仅中文,而且英文
2、第二步,把官网参考文档扫一遍?
翻译 功能 接口
如果英文看不了,就把网页翻译成中文就好啰
稍微看下,有点印象就好,看看提供了哪些功能接口
因为插件的使用是非常简单的
https://gojs.net/latest/intro/index.html
3、gojs插件的移动端支持?
捏合缩放 长按
您可以通过多种方式与此图表进行交互:
- 您可以通过单击选择零件。选定的节点用Adornment突出显示,Adornment是围绕节点的蓝色矩形。所选链接在链接路径后面以蓝线突出显示。
- 可以一次选择多个部件。单击以添加到选择时按住Shift键。单击以切换是否选中该部件时按住Control键。
- 多选的另一种方法是在背景中的某个点(而不是在某个部分上)进行鼠标按下,稍等片刻,然后拖动一个框。选择鼠标向上时框中的部件。Shift和Control修饰符也适用。
- Ctrl-A选择图表中的所有部分。
- 通过选择并拖动来移动一个或多个节点。
- 复制选定的部件可以使用复制/粘贴(Ctrl-C / Ctrl-V)或Ctrl-鼠标拖动。
- 使用Delete键删除所选部件。
- 如果滚动条可见或者整个零件集合小于图表的可视区域(“视口”),则可以在背景中使用鼠标按下平移图表(而不是在零件上)等候。
- 使用鼠标滚轮向上和向下滚动,使用Shift鼠标滚轮向左和向右滚动。Ctrl-mouse-wheel放大和缩小。
您还可以用手指在触摸设备上平移,捏合缩放,选择,复制,移动,删除,撤消和重做。大多数可以从键盘调用的命令都可以从默认的上下文菜单中调用,您可以通过按下手指并保持静止一会儿来获得该命令。
4、go-debug.js和go.js的区别?
错误 检查 调试 开发 生产
在您可以执行任何JavaScript代码来构建Diagram之前,您需要加载GoJS库。当您包含库时,“ go
”JavaScript对象将包含所有GoJS类型。在开发过程中,我们建议您加载“go-debug.js”而不是“go.js”,以获得额外的运行时错误检查和调试功能。
当出现问题时,GoJS会输出错误或警告信息。使用GoJS进行开发时,请务必查看浏览器的开发者控制台以获取信息。库的“go-debug.js”版本包含额外的类型检查和错误检查代码,应该在开发期间使用。“go.js”版本的错误检查较少,但结果更快,应该在生产中使用。
5、go.js中的$符号一般是什么意思?
函数 go.GraphObject.make
var $ = go.GraphObject.make;
其它js库也是把$符号看成一个库,比如jquery
GoJS定义了一个静态函数GraphObject.make,它在构造GraphObjects时非常有用,而不必考虑和跟踪临时变量名。此静态函数还支持以嵌套方式构建对象,其中缩进为您提供了有关可视树中深度的线索,这与上面显示的简单线性代码不同。
GraphObject.make是一个函数,其第一个参数必须是类类型,通常是GraphObject的子类。
GraphObject.make的 其他参数可能有以下几种类型:
- 具有属性/值对的纯JavaScript对象 - 在要构造的对象上设置这些属性值
- 一个GraphObject,作为元素添加到正在构造的Panel中
- 一个GoJS枚举值常量,用作可以接受这样一个值的正在构造的对象的唯一属性的值
- 一个字符串,用于设置正在构造的对象的TextBlock.text,Shape.figure,Picture.source或Panel.type属性
- 一个RowColumnDefinition,用于描述在表的行或列面板小号
- 一个JavaScript数组,持有GraphObject.make的参数,在从函数返回多个参数时很有用
- 以适当方式用于构造对象的其他专用对象
我们可以使用go.GraphObject.make重写上面的代码,以产生完全相同的结果:
1 var $ = go.GraphObject.make; 2 diagram.add( 3 $(go.Node,go.Panel.Auto, 4 $(go.Shape, 5 {图:“RoundedRectangle”, 6 填充:“lightblue” }), 7 $(go.TextBlock, 8 {text:“你好!” , 9 保证金:5 }) 10 ));
6、go.js改变控件样式代码?
go.Brush
1 diagram.add( 2 $(go.Node, "Auto", 3 $(go.Shape, "RoundedRectangle", 4 { fill: $(go.Brush, "Linear", 5 { 0.0: "Violet", 1.0: "Lavender" }) }), 6 $(go.TextBlock, "Hello!", 7 { margin: 5 }) 8 ));
7、go.js的模板模型的使用方式?
数据 模板 分离 template data link
采用的是数据模型和节点模板分离的模式
模板(也就是节点样式)由Diagram.nodeTemplate来设置
节点的数据和节点之间的链接关系由GraphLinksModel.nodeDataArray和GraphLinksModel.linkDataArray来设置
实现节点外观与节点数据分离的一种方法是使用数据模型和节点模板。模型基本上只是一个数据集合,它包含每个节点和每个链接的基本信息。模板基本上只是一个可以复制的部分 ; 您将拥有Node和Link的不同模板。
事实上,一个Diagram已经有非常简单的节点和链接默认模板。如果要自定义图中节点的外观,可以通过设置Diagram.nodeTemplate替换默认节点模板。
要自动使用模板,请提供一个模型,其中包含每个节点的数据和每个链接的数据。甲GraphLinksModel保持节点的数据和链接数据作为值的集合(实际上阵列) GraphLinksModel.nodeDataArray和GraphLinksModel.linkDataArray。然后设置Diagram.model属性,以便该图可以为所有节点数据创建Node,为所有链接数据创建Link。
模型解释和维护数据之间的引用。期望每个节点数据具有唯一的键值,以便可以可靠地解析对节点数据的引用。模型还管理动态添加和删除数据。
模型中的节点数据和链接数据可以是任何JavaScript对象。您可以决定这些对象具有哪些属性 - 添加您的应用程序所需的数量。由于这是JavaScript,您甚至可以动态添加属性。GoJS模型假设存在数个属性,例如“密钥”(在节点数据上)和“类别”和“从”和“到”(后两个在链接数据上)。但是,您可以通过设置名称以“... Property”结尾的模型属性来告诉模型使用不同的属性名称。
节点数据对象通常在“key”属性中具有其节点的唯一键值。目前,节点数据键必须是字符串或数字。您可以通过Node.key属性或通过获取Node的密钥someNode.data.key
。
让我们创建一个图表,提供最少量的必要信息。特定节点数据已放入JavaScript对象数组中。我们在链接数据对象的单独数组中声明链接关系。每个链接数据通过使用其键来保存对节点数据的引用。通常,引用是“from”和“to”属性的值。
var nodeDataArray = [ {key:“Alpha” }, {key:“Beta” } ]。 var linkDataArray = [ {from:“Alpha”,to:“Beta” } ]。diagram.model = new go.GraphLinksModel(nodeDataArray,linkDataArray);

这会产生两个节点和一个链接,但节点不会按我们想要的方式显示。因此,我们将节点模板定义为我们在上面执行的特定节点构造的概括。
diagram.nodeTemplate = //提供自定义节点外观 $(go.Node,“Auto”, $(go.Shape, {图:“RoundedRectangle”, 填充:“白色” }), $(go.TextBlock, {text:“你好!” , 保证金:5 }) ); var nodeDataArray = [ {key:“Alpha” }, {key:“Beta” } ]。 var linkDataArray = [ {from:“Alpha”,to:“Beta” } ]。diagram.model = new go.GraphLinksModel(nodeDataArray,linkDataArray);

8、为什么go.js采用模板(节点样式)和模型(节点数据,节点间的逻辑)分离的方式,为什么不采用用一个函数来创建一个节点的方式?
低效 扩展性
a、更新时刷新低效
b、扩展性不好
让我们尝试构建两个节点并用链接连接它们。这是一种方法:
var node1 = $(go.Node,“Auto”, $(go.Shape, {图:“RoundedRectangle”, 填充:“lightblue” }), $(go.TextBlock, {text:“Alpha”, 保证金:5 }) ) diagram.add(节点1); var node2 = $(go.Node,“Auto”, $(go.Shape, {图:“RoundedRectangle”, 填充:“粉红色” }), $(go.TextBlock, {text:“Beta”, 保证金:5 }) ); diagram.add(节点2); diagram.add( $(go.Link, {fromNode:node1,toNode:node2}, $(go.Shape) ));
这会产生一个漂亮,简单的图表。如果拖动其中一个节点,您将看到该链接仍然与其连接。
虽然这种构建图表的方式可行,但在创建大图时,它不会很好地扩展。通常,您需要不同数量的节点,每个节点与其他节点非常相似。最好分享节点的结构,但参数化一些值应该变化的东西。
一种可能性是将代码构建到一个函数中,该函数返回一个完全构造的Node,包括其可视树中的所有Panel和其他GraphObject。您可能希望参数化该函数,以便提供所需的字符串和颜色以及图形和图像URL。然而,这种方法非常特别:系统很难知道如何自动调用这些功能以便按需创建新节点或新链接。此外,当您的应用程序数据动态更改时,您将如何使用此类函数更新现有节点和链接中现有对象的属性,而不会低效地重新创建所有内容?如果您希望在应用程序数据发生变化时自动更新任何内容/所有内容,系统将如何知道该怎么做?
这个图表构建代码也比管理节点引用需要更麻烦,以便您可以将它们链接起来。这类似于在代码中构建节点的可视化树时必须使用临时命名变量并在需要时引用它们时的早期问题。
我们要寻找的是将所有节点的外观,定义和构造与描述每个特定节点的独特方面所需的应用程序数据分开。
9、go.js中的TreeModel和GraphlinksModel的区别是什么?
简单 没有 链接数据
一种更简单的模型TreeModel仅支持形成树形结构图的链接关系。没有单独的链接数据,因此没有“linkDataArray”。树中固有的父子关系由子节点数据上的额外属性确定,该属性通过其键引用父节点。如果该属性(其名称默认为“parent”)未定义,则该数据的相应节点是树根。每个链接仍然是数据绑定,但链接的数据是子节点数据。
diagram.nodeTemplate = $(go.Node,“Auto”, $(go.Shape, {figure:“Ellipse” }, new go.Binding(“fill”,“color”)), $(go.TextBlock, {margin:5 }, new go.Binding(“text”,“key”)) ); var nodeDataArray = [ {key:“Alpha”,颜色:“lightblue” }, {key:“Beta”,父级:“Alpha”,颜色:“黄色” }, //注意“父级”属性 {key:“Gamma”,父级:“Alpha”,颜色:“orange” }, {key:“Delta”,父母:“Alpha”,颜色:“lightgreen” } ]。diagram.model = new go.TreeModel(nodeDataArray);
10、go.js改变节点让节点闪烁?
事务 数据绑定 setDataProperty
改变节点,改变节点之间的链接关系,比如节点的选中事件等,都是属于数据绑定的操作
all model changes should happen in a transaction
1 diagram.nodeTemplate = 2 $(go.Node, "Auto", 3 { locationSpot: go.Spot.Center }, 4 $(go.Shape, "RoundedRectangle", 5 { // default values if the data.highlight is undefined: 6 fill: "yellow", stroke: "orange", strokeWidth: 2 }, 7 new go.Binding("fill", "highlight", function(v) { return v ? "pink" : "lightblue"; }), 8 new go.Binding("stroke", "highlight", function(v) { return v ? "red" : "blue"; }), 9 new go.Binding("strokeWidth", "highlight", function(v) { return v ? 3 : 1; })), 10 $(go.TextBlock, 11 { margin: 5 }, 12 new go.Binding("text", "key")) 13 ); 14 15 diagram.model.nodeDataArray = [ 16 { key: "Alpha", highlight: false } // just one node, and no links 17 ]; 18 19 function flash() { 20 var model = diagram.model; 21 // all model changes should happen in a transaction 22 model.startTransaction("flash"); 23 var data = model.nodeDataArray[0]; // get the first node data 24 model.setDataProperty(data, "highlight", !data.highlight); 25 model.commitTransaction("flash"); 26 } 27 function loop() { 28 setTimeout(function() { flash(); loop(); }, 500); 29 } 30 loop();
11、添加按钮,并且给按钮添加点击事件?
column item arrays panel
1 diagram.nodeTemplate = 2 $(go.Node, "Auto", 3 $(go.Shape, { fill: "white" }), 4 $(go.Panel, "Table", 5 new go.Binding("itemArray", "people"), 6 { 7 defaultAlignment: go.Spot.Left, 8 itemTemplate: 9 $(go.Panel, "TableRow", 10 new go.Binding("background", "row", 11 function(i) { return i%2 === 0 ? "lightgreen" : "transparent" }) 12 .ofObject(), 13 $(go.TextBlock, new go.Binding("text", "name"), 14 { column: 0, margin: 2, font: "bold 10pt sans-serif" }), 15 $(go.TextBlock, new go.Binding("text", "phone"), 16 { column: 1, margin: 2 }), 17 $(go.TextBlock, new go.Binding("text", "loc"), 18 { column: 2, margin: 2 }), 19 $("Button", 20 { 21 column: 3, 22 margin: new go.Margin(0, 1, 0, 0), 23 click: function(e, obj) { 24 // OBJ is this Button Panel; 25 // find the TableRow Panel containing it 26 var itempanel = obj.panel; 27 alert("Clicked on row " + itempanel.row + " for " + itempanel.data.name); 28 } 29 }, 30 $(go.Shape, "FivePointedStar", 31 { desiredSize: new go.Size(8, 8) }) 32 ) 33 ) // end of itemTemplate 34 }) 35 ); 36 37 diagram.model = 38 $(go.GraphLinksModel, 39 { 40 nodeDataArray: [ 41 { key: "group1", 42 people: [ 43 { name: "Alice", phone: "2345", loc: "C4-E18" }, 44 { name: "Bob", phone: "9876", loc: "E1-B34" }, 45 { name: "Carol", phone: "1111", loc: "C4-E23" }, 46 { name: "Ted", phone: "2222", loc: "C4-E197" }, 47 { name: "Robert", phone: "5656", loc: "B1-A27" }, 48 { name: "Natalie", phone: "5698", loc: "B1-B6" } 49 ] } 50 ] 51 } 52 ); 53 54 diagram.initialContentAlignment = go.Spot.Center;
12、如何改变选中节点的画表颜色(未完)?
selection
Users normally select Parts manually by clicking on them and they deselect them by clicking in the background or pressing the Esc key. You can select parts programmatically by setting Part.isSelected.
You can show that a part is selected by either or both of two general techniques: adding Adornments or changing the appearance of some of the elements in the visual tree of the selected Part.
就在文档的Selection里面:
可以试着去查看修改节点文字的那个函数的源码
node有一个isSelected属性(不是所需代码,只是举例)
function onSelectionChanged(node) { var icon = node.findObject("Icon"); if (icon !== null) { if (node.isSelected) icon.fill = "cyan"; else icon.fill = "lightgray"; } }
然后配上修改节点属性的事务(不是所需代码,只是举例)
changeColor = function() { var model = diagram.model; diagram.startTransaction(); // alternate between lightblue and lightgreen colors var oldcolor = model.modelData.color; var newcolor = (oldcolor === "lightblue" ? "lightgreen" : "lightblue"); model.setDataProperty(model.modelData, "color", newcolor); diagram.commitTransaction("changed shared color"); }
13、使用重定义了$的插件的时候最容易出现的问题是什么,比如gojs做mindmap的时候?
$ 替换 冲突
如下面这段代码,定义了$的值,还是会习惯性的把$当成jQuery来用,所以难免出错
var $ = go.GraphObject.make;
<script> $(function () { //console.log('1111111111'); gojs_init(); gojs_load(); }); </script>
最好的方式是把这个插件(比如这里是go.js)中的$替换成别的,比如$$、Go、$go
var $go = go.GraphObject.make;
这样就互相不冲突了
二、在线mind-map
百度盘下载地址:
1、截图
2、代码
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta name="viewport" content="width=device-width, initial-scale=1"> 5 <title>Mind Map</title> 6 <meta name="description" content="A mind map editor, showing how subtrees can be moved, copied, deleted, and laid out." /> 7 <!-- Copyright 1998-2018 by Northwoods Software Corporation. --> 8 <meta charset="UTF-8"> 9 <script src="go.js"></script> 10 <!--<script src="go-debug.js"></script>--> 11 12 </head> 13 <body onload="init()"> 14 <div id="sample"> 15 <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:300px;"></div> 16 17 <button id="gojs_SaveButton" onclick="gojs_save()">Save</button> 18 <button onclick="jojs_load()">Load</button> 19 <button onclick="gojs_layoutAll()">Layout</button> 20 <button onclick="myDiagram.commandHandler.deleteSelection()">刪除</button> 21 <button onclick="myDiagram.commandHandler.undo()">Undo</button> 22 <button onclick="myDiagram.commandHandler.redo()">Redo</button> 23 <button onclick="myDiagram.commandHandler.editTextBlock()">修改文字</button> 24 <button onclick="fry_gojs_clear()">清空</button> 25 <button id="fry_gojs_add_first_btn" onclick="fry_gojs_add_first()" disabled>增加</button> 26 <input type="color" id="fry_gojs_color"> 27 28 <br /> 29 <textarea id="gojs_mySavedModel" style="width:100%;height:400px;display: none;"> 30 { "class": "go.TreeModel", 31 "nodeDataArray": [ 32 {"key":0, "text":"Mind Map", "loc":"0 0"} 33 ] 34 } 35 </textarea> 36 <script id="code"> 37 function init() { 38 if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this 39 var $ = go.GraphObject.make; 40 myDiagram = 41 $(go.Diagram, "myDiagramDiv", 42 { 43 padding: 20, 44 // when the user drags a node, also move/copy/delete the whole subtree starting with that node 45 "commandHandler.copiesTree": true, 46 "commandHandler.deletesTree": true, 47 "draggingTool.dragsTree": true, 48 initialContentAlignment: go.Spot.Center, // center the whole graph 49 "undoManager.isEnabled": true 50 }); 51 // when the document is modified, add a "*" to the title and enable the "Save" button 52 myDiagram.addDiagramListener("Modified", function(e) { 53 var button = document.getElementById("gojs_SaveButton"); 54 if (button) button.disabled = !myDiagram.isModified; 55 var idx = document.title.indexOf("*"); 56 if (myDiagram.isModified) { 57 if (idx < 0) document.title += "*"; 58 } else { 59 if (idx >= 0) document.title = document.title.substr(0, idx); 60 } 61 }); 62 // a node consists of some text with a line shape underneath 63 myDiagram.nodeTemplate = 64 $(go.Node, "Vertical", 65 { selectionObjectName: "TEXT" }, 66 $(go.TextBlock, 67 { 68 name: "TEXT", 69 minSize: new go.Size(30, 15), 70 editable: true 71 }, 72 // remember not only the text string but the scale and the font in the node data 73 new go.Binding("text", "text").makeTwoWay(), 74 new go.Binding("scale", "scale").makeTwoWay(), 75 new go.Binding("font", "font").makeTwoWay()), 76 $(go.Shape, "LineH", 77 { 78 stretch: go.GraphObject.Horizontal, 79 strokeWidth: 3, height: 3, 80 // this line shape is the port -- what links connect with 81 portId: "", fromSpot: go.Spot.LeftRightSides, toSpot: go.Spot.LeftRightSides 82 }, 83 new go.Binding("stroke", "brush"), 84 // make sure links come in from the proper direction and go out appropriately 85 new go.Binding("fromSpot", "dir", function(d) { return spotConverter(d, true); }), 86 new go.Binding("toSpot", "dir", function(d) { return spotConverter(d, false); })), 87 // remember the locations of each node in the node data 88 new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify), 89 // make sure text "grows" in the desired direction 90 new go.Binding("locationSpot", "dir", function(d) { return spotConverter(d, false); }) 91 ); 92 // selected nodes show a button for adding children 93 myDiagram.nodeTemplate.selectionAdornmentTemplate = 94 $(go.Adornment, "Spot", 95 $(go.Panel, "Auto", 96 // this Adornment has a rectangular blue Shape around the selected node 97 $(go.Shape, { fill: null, stroke: "dodgerblue", strokeWidth: 3 }), 98 $(go.Placeholder, { margin: new go.Margin(4, 4, 0, 4) }) 99 ), 100 // and this Adornment has a Button to the right of the selected node 101 $("Button", 102 { 103 alignment: go.Spot.Right, 104 alignmentFocus: go.Spot.Left, 105 click: addNodeAndLink // define click behavior for this Button in the Adornment 106 }, 107 $(go.TextBlock, "+", // the Button content 108 { font: "bold 8pt sans-serif" }) 109 ) 110 ); 111 // the context menu allows users to change the font size and weight, 112 // and to perform a limited tree layout starting at that node 113 myDiagram.nodeTemplate.contextMenu = 114 $(go.Adornment, "Vertical", 115 $("ContextMenuButton", 116 $(go.TextBlock, "Bigger"), 117 { click: function(e, obj) { changeTextSize(obj, 1.1); } }), 118 $("ContextMenuButton", 119 $(go.TextBlock, "Smaller"), 120 { click: function(e, obj) { changeTextSize(obj, 1/1.1); } }), 121 $("ContextMenuButton", 122 $(go.TextBlock, "Bold/Normal"), 123 { click: function(e, obj) { toggleTextWeight(obj); } }), 124 $("ContextMenuButton", 125 $(go.TextBlock, "Layout"), 126 { 127 click: function(e, obj) { 128 var adorn = obj.part; 129 adorn.diagram.startTransaction("Subtree Layout"); 130 layoutTree(adorn.adornedPart); 131 adorn.diagram.commitTransaction("Subtree Layout"); 132 } 133 } 134 ) 135 ); 136 // a link is just a Bezier-curved line of the same color as the node to which it is connected 137 myDiagram.linkTemplate = 138 $(go.Link, 139 { 140 curve: go.Link.Bezier, 141 fromShortLength: -2, 142 toShortLength: -2, 143 selectable: false 144 }, 145 $(go.Shape, 146 { strokeWidth: 3 }, 147 new go.Binding("stroke", "toNode", function(n) { 148 if (n.data.brush) return n.data.brush; 149 return "black"; 150 }).ofObject()) 151 ); 152 // the Diagram's context menu just displays commands for general functionality 153 myDiagram.contextMenu = 154 $(go.Adornment, "Vertical", 155 $("ContextMenuButton", 156 $(go.TextBlock, "Undo"), 157 { click: function(e, obj) { e.diagram.commandHandler.undo(); } }, 158 new go.Binding("visible", "", function(o) { return o.diagram && o.diagram.commandHandler.canUndo(); }).ofObject()), 159 $("ContextMenuButton", 160 $(go.TextBlock, "Redo"), 161 { click: function(e, obj) { e.diagram.commandHandler.redo(); } }, 162 new go.Binding("visible", "", function(o) { return o.diagram && o.diagram.commandHandler.canRedo(); }).ofObject()), 163 $("ContextMenuButton", 164 $(go.TextBlock, "Save"), 165 { click: function(e, obj) { gojs_save(); } }), 166 $("ContextMenuButton", 167 $(go.TextBlock, "Load"), 168 { click: function(e, obj) { jojs_load(); } }) 169 ); 170 myDiagram.addDiagramListener("SelectionMoved", function(e) { 171 var rootX = myDiagram.findNodeForKey(0).location.x; 172 myDiagram.selection.each(function(node) { 173 if (node.data.parent !== 0) return; // Only consider nodes connected to the root 174 var nodeX = node.location.x; 175 if (rootX < nodeX && node.data.dir !== "right") { 176 updateNodeDirection(node, "right"); 177 } else if (rootX > nodeX && node.data.dir !== "left") { 178 updateNodeDirection(node, "left"); 179 } 180 layoutTree(node); 181 }); 182 gojs_save(); 183 gojs_layoutAll() 184 }); 185 // read in the predefined graph using the JSON format data held in the "gojs_mySavedModel" textarea 186 jojs_load(); 187 } 188 function spotConverter(dir, from) { 189 if (dir === "left") { 190 return (from ? go.Spot.Left : go.Spot.Right); 191 } else { 192 return (from ? go.Spot.Right : go.Spot.Left); 193 } 194 } 195 function changeTextSize(obj, factor) { 196 var adorn = obj.part; 197 adorn.diagram.startTransaction("Change Text Size"); 198 var node = adorn.adornedPart; 199 var tb = node.findObject("TEXT"); 200 tb.scale *= factor; 201 adorn.diagram.commitTransaction("Change Text Size"); 202 } 203 function toggleTextWeight(obj) { 204 var adorn = obj.part; 205 adorn.diagram.startTransaction("Change Text Weight"); 206 var node = adorn.adornedPart; 207 var tb = node.findObject("TEXT"); 208 // assume "bold" is at the start of the font specifier 209 var idx = tb.font.indexOf("bold"); 210 if (idx < 0) { 211 tb.font = "bold " + tb.font; 212 } else { 213 tb.font = tb.font.substr(idx + 5); 214 } 215 adorn.diagram.commitTransaction("Change Text Weight"); 216 } 217 function updateNodeDirection(node, dir) { 218 myDiagram.model.setDataProperty(node.data, "dir", dir); 219 // recursively update the direction of the child nodes 220 var chl = node.findTreeChildrenNodes(); // gives us an iterator of the child nodes related to this particular node 221 while(chl.next()) { 222 updateNodeDirection(chl.value, dir); 223 } 224 } 225 //var fry_brush_group=['skyblue','darkseagreen','palevioletred','coral']; 226 //console.log(fry_brush_group[Math.floor(Math.random()*fry_brush_group.length)]); 227 function addNodeAndLink(e, obj) { 228 //console.log(e); 229 //console.log(obj); 230 var adorn = obj.part; 231 var diagram = adorn.diagram; 232 diagram.startTransaction("Add Node"); 233 var oldnode = adorn.adornedPart; 234 var olddata = oldnode.data; 235 //console.log(olddata.brush); 236 //如果沒定義筆刷,就在數組裡面隨機選就好了,多簡單 237 //var fry_brush_group=['skyblue','darkseagreen','palevioletred','coral','palegreen']; 238 //if(typeof olddata.brush == "undefined") olddata.brush=fry_brush_group[Math.floor(Math.random()*fry_brush_group.length)]; 239 olddata.brush=document.getElementById("fry_gojs_color").value; 240 //console.log(olddata.brush); 241 // copy the brush and direction to the new node data 242 var newdata = { text: "idea", brush: olddata.brush, dir: olddata.dir, parent: olddata.key }; 243 diagram.model.addNodeData(newdata); 244 layoutTree(oldnode); 245 diagram.commitTransaction("Add Node"); 246 // if the new node is off-screen, scroll the diagram to show the new node 247 var newnode = diagram.findNodeForData(newdata); 248 if (newnode !== null) diagram.scrollToRect(newnode.actualBounds); 249 gojs_layoutAll(); 250 } 251 function layoutTree(node) { 252 if (node.data.key === 0) { // adding to the root? 253 gojs_layoutAll(); // lay out everything 254 } else { // otherwise lay out only the subtree starting at this parent node 255 var parts = node.findTreeParts(); 256 layoutAngle(parts, node.data.dir === "left" ? 180 : 0); 257 } 258 } 259 function layoutAngle(parts, angle) { 260 var layout = go.GraphObject.make(go.TreeLayout, 261 { angle: angle, 262 arrangement: go.TreeLayout.ArrangementFixedRoots, 263 nodeSpacing: 5, 264 layerSpacing: 20, 265 setsPortSpot: false, // don't set port spots since we're managing them with our spotConverter function 266 setsChildPortSpot: false }); 267 layout.doLayout(parts); 268 } 269 function gojs_layoutAll() { 270 var root = myDiagram.findNodeForKey(0); 271 if (root === null) return; 272 myDiagram.startTransaction("Layout"); 273 // split the nodes and links into two collections 274 var rightward = new go.Set(go.Part); 275 var leftward = new go.Set(go.Part); 276 root.findLinksConnected().each(function(link) { 277 var child = link.toNode; 278 if (child.data.dir === "left") { 279 leftward.add(root); // the root node is in both collections 280 leftward.add(link); 281 leftward.addAll(child.findTreeParts()); 282 } else { 283 rightward.add(root); // the root node is in both collections 284 rightward.add(link); 285 rightward.addAll(child.findTreeParts()); 286 } 287 }); 288 // do one layout and then the other without moving the shared root node 289 layoutAngle(rightward, 0); 290 layoutAngle(leftward, 180); 291 myDiagram.commitTransaction("Layout"); 292 } 293 // Show the diagram's model in JSON format 294 function gojs_save() { 295 document.getElementById("gojs_mySavedModel").value = myDiagram.model.toJson(); 296 myDiagram.isModified = false; 297 } 298 function jojs_load() { 299 myDiagram.model = go.Model.fromJson(document.getElementById("gojs_mySavedModel").value); 300 //console.log(myDiagram.model); 301 } 302 //清空 303 function fry_gojs_clear() { 304 document.getElementById("gojs_mySavedModel").value='{ "class": "go.TreeModel","nodeDataArray": []}'; 305 document.getElementById("fry_gojs_add_first_btn").disabled=""; 306 jojs_load(); 307 } 308 //增加最初那個節點 309 function fry_gojs_add_first(){ 310 document.getElementById("gojs_mySavedModel").value='{ "class": "go.TreeModel","nodeDataArray": [{"key":0, "text":"Mind Map", "loc":"0 0"}]}'; 311 document.getElementById("fry_gojs_add_first_btn").setAttribute('disabled','disabled'); 312 jojs_load(); 313 } 314 //改變選中的 315 </script> 316 </div> 317 </body> 318 </html>