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>
