gojs树以及伸缩功能的实现(react)

一、树的展示

展示效果:
在这里插入图片描述
代码:

export default class indexTree extends Component {
    
    
    static propTypes = {
    
    };

    constructor(props) {
    
    
        super(props);
        this.diagramRef = React.createRef();
        this.state = {
    
    
            nodeDataArray: [
                {
    
     key: 1, text: 'No flow to receiver', figure: 'None' },
                {
    
    
                    key: 2,
                    text: 'No flow from Component B',
                    parent: 1,
                    figure: 'OrGate',
                    choice: 'G02'
                },
                {
    
    
                    key: 3,
                    text: 'No flow into Component B',
                    parent: 2,
                    figure: 'AndGate',
                    choice: 'G03'
                },
                {
    
    
                    key: 4,
                    text: 'Component B blocks flow',
                    parent: 2,
                    figure: 'Circle',
                    choice: 'B01'
                },
                {
    
    
                    key: 5,
                    text: 'No flow from Component A1',
                    parent: 3,
                    figure: 'OrGate',
                    choice: 'G04'
                },
                {
    
    
                    key: 6,
                    text: 'No flow from Component A2',
                    parent: 3,
                    figure: 'OrGate',
                    choice: 'G05'
                },
                {
    
    
                    key: 7,
                    text: 'No flow from source1',
                    parent: 5,
                    figure: 'Triangle',
                    choice: 'T01'
                },
                {
    
    
                    key: 8,
                    text: 'Component A1 blocks flow',
                    parent: 5,
                    figure: 'Circle',
                    fill: 'green',
                    choice: 'B02'
                },
                {
    
    
                    key: 9,
                    text: 'No flow from source2',
                    parent: 6,
                    figure: 'Triangle',
                    choice: 'T02'
                },
                {
    
    
                    key: 10,
                    text: 'Component A2 blocks flow',
                    parent: 6,
                    figure: 'Circle',
                    choice: 'B03'
                }
            ]
        };
    }
    componentDidMount() {
    
    }

    initDiagram() {
    
    
        const $ = go.GraphObject.make;
        // 1、初始化画布
        const diagram = $(go.Diagram, {
    
    
            allowCopy: false,
            allowDelete: false,
            'draggingTool.dragsTree': true,
            'undoManager.isEnabled': true
        });
        diagram.layout = $(go.TreeLayout, {
    
    
            angle: 90,
            layerSpacing: 30
        });
        diagram.model = $(go.TreeModel, {
    
    
            // linkKeyProperty: 'key' // 使用GraphLinksModel时应始终设置此项
        });

        diagram.addDiagramListener('ObjectSingleClicked', function (e) {
    
    
            console.log(e);
            console.log(e.subject);
            console.log(e.parameter);
        });

        // 树折叠事件
        diagram.addDiagramListener('TreeCollapsed', function (e) {
    
    
            // console.log(e);
            // console.log('折叠');
        });

        // 树展开事件
        diagram.addDiagramListener('TreeExpanded', function (e) {
    
    
            // console.log(e);
            // console.log('展开');
        });

        // 面板的颜色
        function nodeFillConverter(figure) {
    
    
            switch (figure) {
    
    
                case 'AndGate':
                    // right to left so when it's rotated, it goes from top to bottom
                    return $(go.Brush, 'Linear', {
    
    
                        0: '#EA8100',
                        1: '#C66D00',
                        start: go.Spot.Right,
                        end: go.Spot.Left
                    });
                case 'OrGate':
                    return $(go.Brush, 'Linear', {
    
    
                        0: '#0058D3',
                        1: '#004FB7',
                        start: go.Spot.Right,
                        end: go.Spot.Left
                    });
                case 'Circle':
                    return $(go.Brush, 'Linear', {
    
    
                        0: '#009620',
                        1: '#007717'
                    });
                case 'Triangle':
                    return $(go.Brush, 'Linear', {
    
    
                        0: '#7A0099',
                        1: '#63007F'
                    });
                case 'Diamond':
                    return $(go.Brush, 'Linear', {
    
    
                        0: '#fff',
                        1: '#fff'
                    });
                default:
                    return 'whitesmoke';
            }
        }

        /**
         * 边框样式设置
         * @param {type} 判断是测点还是指标
         */
        function borderStroke(type) {
    
    
            switch (type) {
    
    
                case 'cd':
                    return '#8EDA87';
                case 'zb':
                    return borderColor;
                default:
                    return borderColor;
            }
        }

        // 2、定义node模型
        diagram.nodeTemplate = $(
            go.Node,
            'Spot', // 形状将围绕TextBlock
            {
    
    
                selectionObjectName: 'BODY',
                locationSpot: go.Spot.Center,
                locationObjectName: 'BODY',
                //movable: false, //禁止拖动
                deletable: false //禁止删除
            },
            $(
                go.Panel,
                'Auto',
                {
    
    
                    name: 'BODY',
                    portId: ''
                },
                $(
                    go.Shape,
                    'RoundedRectangle',
                    {
    
    
                        // 面板样式
                        fill: $(go.Brush, 'Linear', {
    
    
                            0: '#fff',
                            1: '#fff'
                        })
                        //stroke: borderColor
                    },
                    new go.Binding('type'),
                    new go.Binding('stroke', 'type', borderStroke) // 内容的颜色
                ),
                $(
                    go.TextBlock,
                    {
    
    
                        // 字体样式
                        margin: new go.Margin(5, 10, 5, 10),
                        maxSize: new go.Size(100, NaN), // 字体大小
                        stroke: 'rgba(0, 0, 0, .90)', // 字体颜色
                        font: '10pt Segoe UI, sans-serif'
                    },
                    new go.Binding('text')
                ),
                {
    
    
                    click: function (e, node) {
    
    
                        // 双击事件
                        console.log(node);
                    }
                }
            ),
            // 线
            $(
                go.Shape,
                'LineV',
                new go.Binding('visible', 'figure', function (f) {
    
    
                    return f !== 'None';
                }),
                {
    
    
                    strokeWidth: strokeWidth,
                    height: 30, // 底部的线的高度
                    alignment: new go.Spot(0.5, 1, 0, 17), // x, y, offx, offy
                    alignmentFocus: go.Spot.Center,
                    stroke: borderColor // 边框的颜色
                }
            ),
            // 边框
            $(
                go.Shape,
                new go.Binding('visible', 'figure', function (f) {
    
    
                    return f !== 'None';
                }),
                {
    
    
                    alignment: new go.Spot(0.5, 1, 0, 30), // x, y, offx, offy
                    alignmentFocus: go.Spot.Top,
                    width: 40,
                    height: 30,
                    stroke: borderColor // 边框的颜色
                },
                new go.Binding('figure'),
                new go.Binding('fill', 'figure', nodeFillConverter), // 内容的颜色
                new go.Binding('angle', 'figure', function (f) {
    
    
                    // 旋转角度
                    return f === 'OrGate' || f === 'AndGate' ? -90 : 0;
                })
            ),
            $(
                go.TextBlock,
                new go.Binding('visible', 'figure', function (f) {
    
    
                    return f !== 'None';
                }), // if we don't have a figure, don't display any choice text
                {
    
    
                    alignment: new go.Spot(0.5, 1, 25, 45),
                    alignmentFocus: go.Spot.Left,
                    stroke: 'black',
                    font: '10pt Segoe UI, sans-serif'
                },
                new go.Binding('text', 'choice')
            ),
            $(
                'TreeExpanderButton',
                {
    
    
                    alignment: new go.Spot(0.5, 1, 0, 0),
                    alignmentFocus: go.Spot.Top,
                    'ButtonBorder.figure': 'Rectangle'
                },
                new go.Binding('fill', '#fff')
            )
        );

        diagram.linkTemplate = $(
            go.Link,
            {
    
    
                routing: go.Link.Orthogonal, // may be either Orthogonal or AvoidsNodes
                curve: go.Link.JumpOver
            },
            {
    
    
                layerName: 'Background',
                curviness: 20,
                corner: 5
            },
            $(go.Shape, {
    
    
                strokeWidth: strokeWidth,
                stroke: borderColor // 边框的颜色
            }),
            $(go.Shape, {
    
    
                toArrow: 'Standard', // 箭头
                stroke: borderColor, // 边框的颜色
                fill: $(go.Brush, 'Linear', {
    
    
                    // 填充色
                    0: borderColor,
                    1: borderColor
                })
            })
        );

        return diagram;
    }

    onModelChange = (obj) => {
    
    
        const insertedNodeKeys = obj.insertedNodeKeys; //新增的节点
        const modifiedNodeData = obj.modifiedNodeData; //改变的节点
        const removedNodeKeys = obj.removedNodeKeys; //删除的节点
        const insertedLinkKeys = obj.insertedLinkKeys; //新增的连线
        const modifiedLinkData = obj.modifiedLinkData; //改变的连线
        const removedLinkKeys = obj.removedLinkKeys; //删除的连线
        const modifiedModelData = obj.modelData;
    };

    render() {
    
    
        return (
            <div>
                <ReactDiagram
                    initDiagram={
    
    this.initDiagram}
                    divClassName="diagram-component"
                    nodeDataArray={
    
    this.state.nodeDataArray}
                    onModelChange={
    
    this.onModelChange}
                />{
    
    ' '}
            </div>
        );
    }
}

二、实现点击节点,实现扩展收缩的功能

官方文档上有例子实现了此功能,根据这个例子做的更改:决策树图案例。但是里面的收缩方法有问题,每次只能收缩一个子节点,需要一个个的点击,主要的问题出在了递归调用这里:
在这里插入图片描述
解决方案1:

var node = port.part;
node.diagram.startTransaction('expand/collapse');
 var portid = port.portId;
 if (
     node.findLinksOutOf(portid).first() &&
     node.findLinksOutOf(portid).first().visible
 ) {
    
    
     // 递归折叠整个子树
     collapseTree(node, portid);
 } else {
    
    
     node.findLinksOutOf(portid).each(function (l) {
    
    
         if (!l.visible) {
    
    
             // 只扩展直接子级及其链接
             l.visible = true;
             var n = l.getOtherNode(node);
             if (n !== null) {
    
    
                 n.location = node.getDocumentPoint(go.Spot.TopRight);
                 n.visible = true;
             }
         }
     });
 }

添加了判断,判断第一条数据是否存在,存在的时候判断visible的值,如果是true的话就收缩,如果是false的话就展开。
解决方案2:

let bool = true;
node.findLinksOutOf(portid).each(function (l) {
    
    
    if (bool) {
    
    
        if (l.visible) {
    
    
            // 递归折叠整个子树
            collapseTree(node, portid);
            bool = false;
        } else {
    
    
            // console.log('扩展');
            // 只扩展直接子级及其链接
            l.visible = true;
            var n = l.getOtherNode(node);
            if (n !== null) {
    
    
                n.location = node.getDocumentPoint(go.Spot.TopRight);
                n.visible = true;
            }
        }
    }
});

添加了一个bool值,约束其收缩的时候,只执行一次;
使用的时候:
(1)可以绑定点击事件

diagram.addDiagramListener('ObjectSingleClicked', function (e) {
    
    
	const port = e.port; .// port应该是从e对象中取
	buttonExpandCollapse(e, port);
});

(2)可以在Panel里面使用click方法:

$(
     go.Panel,
     'Auto',
     {
    
    
         name: 'BODY',
         portId: ''
     },
     $(
         go.Shape,
         'RoundedRectangle',
         {
    
    
             // 面板样式
             fill: $(go.Brush, 'Linear', {
    
    
                 0: '#fff',
                 1: '#fff'
             })
             //stroke: borderColor
         },
         new go.Binding('type'),
         new go.Binding('stroke', 'type', borderStroke) // 内容的颜色
     ),
     $(
         go.TextBlock,
         {
    
    
             // 字体样式
             margin: new go.Margin(5, 10, 5, 10),
             maxSize: new go.Size(100, NaN), // 字体大小
             stroke: 'rgba(0, 0, 0, .90)', // 字体颜色
             font: '10pt Segoe UI, sans-serif'
         },
         new go.Binding('text')
     ),
     {
    
    
         click: function (e, node) {
    
    
             // 点击事件
             buttonExpandCollapse(e, node);
         }
     }
 ),

猜你喜欢

转载自blog.csdn.net/qq_28013889/article/details/107346705