JavaScript is required

展示全部按钮

前置加载节点的显示全部选项 - 预加载所有数据但初始仅显示有限节点,按需显示全部

前置加载节点的显示全部选项

功能概述

本示例演示了显示大量子节点的"显示全部"模式。它不是使用分页延迟加载,而是预加载所有数据但初始隐藏超出默认可见数量(每个分类 3 个节点)的节点。用户可以点击"显示更多"按钮一次性显示所有隐藏的节点。这种方法提供对完整数据集的快速访问,同时保持简洁的初始视图。

核心特性实现

部分可见的初始数据加载

appendTypeData 函数加载所有节点但将大部分标记为隐藏:

const appendTypeData = async (myType: string) => {
    const typeNode = graphInstance.getNodes().find(n => n.data.myType === myType);
    const defaultVisibleCount = 3;
    const allItems = await loadMockCompanys(myType);
    const total = allItems.length;

    const thisTypeJsonData: RGJsonData = { nodes: [], lines: [] };
    for (const entItem of allItems) {
        const companyNode: JsonNode = {
            id: entItem.companyId,
            text: entItem.companyName,
            data: { ownerType: myType }
        };
        // 隐藏超出默认可见数量的节点
        if (thisTypeJsonData.nodes.length > defaultVisibleCount) {
            companyNode.hidden = true;
        }
        thisTypeJsonData.nodes.push(companyNode);
        thisTypeJsonData.lines.push({ from: typeNodeId, to: companyNode.id });
    }
    updateLoadMoreButtonNode(typeNodeId, myType, defaultVisibleCount - 1, total, thisTypeJsonData);

    // 将新节点定位在父节点位置以实现平滑动画
    thisTypeJsonData.nodes.forEach((n: JsonNode) => {
        n.x = typeNode.x;
        n.y = typeNode.y;
    });

    graphInstance.addNodes(thisTypeJsonData.nodes);
    graphInstance.addLines(thisTypeJsonData.lines);
};

关键要点:

  • 所有数据预加载:预先获取完整数据集
  • 选择性可见:默认仅显示前 3 个节点
  • 隐藏属性:使用 node.hidden = true 隐藏多余节点
  • 批量添加:一次性将所有节点添加到图中以提高效率

显示全部功能

showAllNodes 函数显示某个分类的所有隐藏节点:

const showAllNodes = async(buttonNode: RGNode) => {
    const myType = buttonNode.data.loadType;
    const typeNodes = graphInstance.getNodes().filter(n => n.data.ownerType === myType);

    // 取消隐藏此类型的所有节点
    typeNodes.forEach(n => {
        graphInstance.updateNode(n.id, { hidden: false });
    });

    // 删除"显示更多"按钮
    graphInstance.removeNodeById(buttonNode.id);
    await graphInstance.doLayout();
};

关键要点:

  • 按类型过滤:仅检索匹配分类类型的节点
  • 批量更新:一次性更新所有相关节点的可见性
  • 按钮移除:显示节点后删除"显示更多"按钮
  • 布局刷新:显示所有节点后重新计算位置

显示更多按钮管理

updateLoadMoreButtonNode 函数添加显示剩余数量的按钮:

const updateLoadMoreButtonNode = (
    typeNodeId: string,
    myType: string,
    fromIndex: number,
    total: number,
    currentPageGraphJsonData: RGJsonData
) => {
    const loadNextPageButtonNodeId = `${myType}-next-button`;
    graphInstance.removeNodeById(loadNextPageButtonNodeId);

    const remainingItemCount = total - fromIndex + 1;
    if (remainingItemCount > 0) {
        const loadNextPageButtonNode = {
            id: loadNextPageButtonNodeId,
            text: `Show More(${remainingItemCount})`,
            data: { myType: 'more-btn', loadType: myType, fromIndex: (fromIndex + 1) }
        };
        currentPageGraphJsonData.nodes.push(loadNextPageButtonNode);
        currentPageGraphJsonData.lines.push({
            from: typeNodeId,
            to: loadNextPageButtonNode.id
        });
    }
};

带点击处理器的自定义节点插槽

NodeSlot 组件处理"显示更多"按钮点击:

const NodeSlot: React.FC<RGNodeSlotProps & {showAllNodes: (n: RGNode) => void|Promise<void>}> = ({ node, showAllNodes }) => {
    const myType = node.data.myType;
    const buttonTypes = ['investment-button', 'shareholder-button', 'historical-investment-button', 'historical-shareholder-button'];

    return (
      <>
        {buttonTypes.includes(myType) && (
          <div className="my-node my-button-node">{node.text}</div>
        )}
        {myType === 'root' && (
          <div className="my-node my-root">{node.text}</div>
        )}
        {myType === 'more-btn' && (
          <div className="my-node more-btn px-2" onClick={() => {showAllNodes(node)}}>
            {node.text}
          </div>
        )}
        {!myType && (
          <div className="my-node">{node.text}</div>
        )}
      </>
    );
};

多分类初始化

图初始化时有四个分类节点,每个都有预加载的隐藏子节点:

const initializeGraph = async () => {
    const myJsonData: RGJsonData = {
        rootId: 'root',
        nodes: [
            { id: 'root', text: 'Tian Technology Co., Ltd.', expandHolderPosition: 'hide', data: { myType: 'root' } },
            { id: 'root-invs', text: 'Investment', disablePointEvent: true, data: { myType: 'investment-button', childrenLoaded: false } },
            { id: 'root-history-invs', text: 'Historical Investment', data: { myType: 'historical-investment-button', childrenLoaded: false } },
            { id: 'root-sh', text: 'Share Holder', disablePointEvent: true, data: { myType: 'shareholder-button', childrenLoaded: false } },
            { id: 'root-history-shareholder', text: 'Historical Share Holder', data: { myType: 'historical-shareholder-button', childrenLoaded: false } }
        ],
        lines: [
            { from: 'root', to: 'root-invs', showEndArrow: false },
            { from: 'root', to: 'root-history-invs', showEndArrow: false },
            { from: 'root', to: 'root-sh', showEndArrow: false },
            { from: 'root', to: 'root-history-shareholder', showEndArrow: false }
        ]
    };

    graphInstance.loading();
    await graphInstance.setJsonData(myJsonData);

    // 使用部分可见性预加载所有分类
    await appendTypeData('investment-button');
    await appendTypeData('shareholder-button');
    await appendTypeData('historical-investment-button');
    await appendTypeData('historical-shareholder-button');

    await graphInstance.sleep(400);
    await graphInstance.doLayout();
    graphInstance.clearLoading();
    graphInstance.moveToCenter();
    graphInstance.zoomToFit();
};

树形布局配置

const graphOptions: RGOptions = {
    defaultExpandHolderPosition: 'right',
    defaultNodeShape: RGNodeShape.rect,
    defaultNodeBorderWidth: 0,
    defaultLineShape: RGLineShape.StandardOrthogonal,
    defaultPolyLineRadius: 5,
    defaultJunctionPoint: RGJunctionPoint.lr,
    reLayoutWhenExpandedOrCollapsed: true,
    layout: {
        layoutName: 'tree',
        from: 'left',
        treeNodeGapH: 100,
        treeNodeGapV: 10,
        alignItemsX: 'start',
        alignParentItemsX: 'end',
    }
};

创意使用场景

企业结构可视化: 显示企业集团的所有子公司,但初始仅显示关键部门。高管可以在需要详细分析时展开查看所有子单元。

产品目录浏览: 显示每个分类的前 3 个产品,隐藏其余产品。购物者可以点击"显示更多"来显示他们感兴趣的分类中的完整产品线。

组织架构图浏览器: 渲染公司层级结构,直接报告限制为 3 个。用户可以在需要完整可见性时显示部门内的所有团队成员。

网络依赖关系图: 可视化系统依赖关系,初始仅显示关键依赖项。开发人员在排查复杂系统问题时可以展开查看所有连接。

文件系统浏览器: 显示文件夹内容,仅前 3 个文件可见。用户可以在搜索特定项目时显示目录中的所有文件,而无需导航离开。