使用go.js 创建完全二叉树的图形


先来个效果图感受一下子go.js的神奇之处。(该图片是个动图。。。)

这个效果是go.js中的LocalView 视图。

接下来就是实现步骤了。

一、Go.js 插件下载

官方 go.js 下载地址:http:/https://gojs.net/latest/doc/download.html/
作者分享地址:go.js下载 密码:c205

官方下载的源码内部有简单的demo和API
源码好像内嵌版本说明防伪水印,需要付费下载正版无水印源码的样子

天朝规则:无水印源码下载链接 (反正我在源码中找到了那段很长的但看起来毫无作用的变量,删掉就无水印了,并且目前没影响到插件的使用。)

二、添加依赖

因为go.js 依赖于 h5 的标准,所以页面必须使用 h5标准声明

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>

    </body>
    </html>

三、使用步骤

创建一个div,gojs 渲染的图层,任意给了div就可以了。

<div id="sample">
                <div id="fullDiagram" style="height:250px;width:100%;border:1px solid black;margin:2px"></div>
                <div id="localDiagram" style="height:350px;width:100%;border:1px solid black;margin:2px"></div>
                <button onclick="setupDiagram()">Create New Tree</button>
            </div>

我实现该效果的具体代码如下:

(只实现了这一个效果,想使用其他效果的砖友们可以去官网看demo,这里就不一一介绍了。)

(1)div中的代码:
<div id="sample">
                <div id="fullDiagram" style="height:250px;width:100%;border:1px solid black;margin:2px"></div>
                <div id="localDiagram" style="height:350px;width:100%;border:1px solid black;margin:2px"></div>
                <button onclick="setupDiagram()">Create New Tree</button>
            </div>
(2)JavaScript中的代码:
    <script id="code">
        function init() {
            // if (window.goSamples) goSamples();  // 对于这些样本,你不需要调用它
            var $ = go.GraphObject.make;  // 用于定义模板的简洁性

            myFullDiagram =
                $(go.Diagram, "fullDiagram",  // 每个图都用id表示它的div HTML元素
                    {
                        initialAutoScale: go.Diagram.UniformToFill,  // 自动缩放以显示整棵树
                        maxScale: 0.25,
                        contentAlignment: go.Spot.Center,  // 将树置于视窗中
                        isReadOnly: true,  // 不允许用户更改图表
                        "animationManager.isEnabled": false,
                        layout: $(go.TreeLayout,
                            {angle: 90, sorting: go.TreeLayout.SortingAscending}),
                        maxSelectionCount: 1,  // 每个图中只能选择一个节点。
                        // 当选择更改时,更新 myLocalDiagram 视图
                        "ChangedSelection": showLocalOnFullClick
                    });

            myLocalDiagram =  // 这和完整的图非常相似
                $(go.Diagram, "localDiagram",
                    {
                        autoScale: go.Diagram.UniformToFill,
                        contentAlignment: go.Spot.Center,
                        isReadOnly: true,
                        layout: $(go.TreeLayout,
                            {angle: 90, sorting: go.TreeLayout.SortingAscending}),
                        "LayoutCompleted": function (e) {
                            var sel = e.diagram.selection.first();
                            if (sel !== null) myLocalDiagram.scrollToRect(sel.actualBounds);
                        },
                        maxSelectionCount: 1,
                        // 当选择更改时,更新 myLocalDiagram 的内容。
                        "ChangedSelection": showLocalOnLocalClick
                    });

            // 定义两个图共享的节点模板
            var myNodeTemplate =
                $(go.Node, "Auto",
                    {locationSpot: go.Spot.Center},
                    new go.Binding("text", "key", go.Binding.toString),  // 进行排序
                    $(go.Shape, "Rectangle",
                        new go.Binding("fill", "color"),
                        {stroke: null}),
                    $(go.TextBlock,
                        {margin: 5},
                        new go.Binding("text", "key", function (k) {
                            return "u00000000" + k;
                        }))
                );
            myFullDiagram.nodeTemplate = myNodeTemplate;
            myLocalDiagram.nodeTemplate = myNodeTemplate;

            // 定义一个基本的链接模板,不可选择,由两个图共享
            var myLinkTemplate =
                $(go.Link,
                    {routing: go.Link.Normal, selectable: false},
                    $(go.Shape,
                        {strokeWidth: 1})
                );
            myFullDiagram.linkTemplate = myLinkTemplate;
            myLocalDiagram.linkTemplate = myLinkTemplate;

            // 创建完整的树图
            setupDiagram();

            // 在整个图的背景中创建一个部分来突出选中的节点
            highlighter =
                $(go.Part, "Auto",
                    {
                        layerName: "Background",
                        selectable: false,
                        isInDocumentBounds: false,
                        locationSpot: go.Spot.Center
                    },
                    $(go.Shape, "Ellipse",
                        {
                            fill: $(go.Brush, "Radial", {0.0: "yellow", 1.0: "white"}),
                            stroke: null,
                            desiredSize: new go.Size(400, 400)
                        })
                );
            myFullDiagram.add(highlighter);

            // 首先,将图表集中在树顶部的节点上
            // 在选择根节点之前,等待树的布局
            myFullDiagram.addDiagramListener("InitialLayoutCompleted", function (e) {
                var node0 = myFullDiagram.findPartForKey(0);
                if (node0 !== null) node0.isSelected = true;
                showLocalOnFullClick();
            });
        }

        // 在选中的本地图中,使相应的节点在全图中选择
        // 然后调用showLocalOnFullClick 来更新本地图。
        function showLocalOnLocalClick() {
            var selectedLocal = myLocalDiagram.selection.first();
            if (selectedLocal !== null) {
                // 有两个独立的节点,每个节点一个,但它们共享相同的键值
                myFullDiagram.select(myFullDiagram.findPartForKey(selectedLocal.data.key));
            }
        }

        function showLocalOnFullClick() {
            var node = myFullDiagram.selection.first();
            if (node !== null) {
                // 确保选中的节点在viewport中
                myFullDiagram.scrollToRect(node.actualBounds);
                // 移动选定节点后面的大黄色节点以突出显示。
                highlighter.location = node.location;
                // 为本地图创建一个新模型
                var model = new go.TreeModel();
                // 将选定的节点及其子节点和子节点添加到本地图中
                var nearby = node.findTreeParts(3);  // 三层(子)树
                // 增加父母和祖父母
                var parent = node.findTreeParentNode();
                if (parent !== null) {
                    nearby.add(parent);
                    var grandparent = parent.findTreeParentNode();
                    if (grandparent !== null) {
                        nearby.add(grandparent);
                    }
                }
                // 使用与myFullDiagram 模型相同的节点数据创建模型
                nearby.each(function (n) {
                    if (n instanceof go.Node) model.addNodeData(n.data);
                });
                myLocalDiagram.model = model;
                // 在图的焦点上选择节点
                var selectedLocal = myLocalDiagram.findPartForKey(node.data.key);
                if (selectedLocal !== null) selectedLocal.isSelected = true;
            }
        }

        // 创建包含总节点的树模型,每个节点有多个子节点
        function setupDiagram(total) {
            if (total === undefined) total = 11;  // 默认为100个节点
            var nodeDataArray = [];

            //  节点的key值和颜色
            for (var i = 0; i < total; i++) {
                nodeDataArray.push({
                    key: nodeDataArray.length,
                    color: go.Brush.randomColor()
                });
            }

            //  自己创建完全二叉树的结构
            var j = 0;
            for (var i = 1; i < total; i++) {
                var data = nodeDataArray[i];
                if (i <= 2) {
                    data.parent = 0;
                }
                if (i == 3 || i == 4) {
                    data.parent = 1;
                }
                if (i == 5 || i == 6) {
                    data.parent = 2;
                }

                if (i == 7 || i == 8) {
                    data.parent = 3;
                }

                if (i == 9 || i == 10) {
                    data.parent = 4;
                }

                // if (Math.random() < 0.3) j++;  // 这就控制了有足够的孩子的可能性
            }

            myFullDiagram.model = new go.TreeModel(nodeDataArray);
        }
    </script>

到此结束。
该内容仅供参考,如有错误欢迎砖友们指出。

发表评论

电子邮件地址不会被公开。 必填项已用*标注