一些图表的实现

一、relation-graph 的使用案例

1、可展开收起的关系图

先看效果:
在这里插入图片描述
上代码:

<!-- eslint-disable vue/multi-word-component-names -->
<template>
    <div style="width: 100%; height: 100%" class="relationGraph">
        <RelationGraph
            ref="relationGraphRef"
            :options="graphOptions"
            @on-node-click="onNodeClick"
            @on-line-click="onLineClick"
            @on-node-drag-end="onNodeDragEnd"
            @on-node-expand="onNodeExpand"
            @on-node-collapse="onNodeCollapse"
        />
    </div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue'
import RelationGraph from 'relation-graph-vue3'
import type {
    RGJsonData,
    RGNode,
    RGOptions,
    RGUserEvent
} from 'relation-graph-vue3'

// 获取关系图实例的引用
const relationGraphRef: any = ref(null)
const resizeTimer = ref()

// 设置图表的基本选项
const graphOptions = ref<any>({
    allowShowMiniToolBar: true, // 允许显示迷你工具栏
    allowShowZoomMenu: true, // 允许显示缩放菜单
    allowShowDownloadButton: false, // 禁止显示下载按钮
    allowAutoLayoutIfSupport: false, // 允许自动布局
    defaultExpandHolderPosition: 'right', // 默认展开方向为右
    defaultJunctionPoint: 'border', // 默认连线点为边框
    debug: false, // 禁止调试模式
    showDebugPanel: false, // 不显示调试面板
    moveToCenterWhenRefresh: false, // 禁止刷新时移动到中心
    zoomToFitWhenRefresh: false, // 禁止刷新时自动缩放以适应屏幕
    useAnimationWhenRefresh: true, // 刷新时使用动画
    layout: {
        layoutName: 'force', // 自动布局
        from: 'left', // 默认left——从左到右
        maxLayoutTimes: 10000, // 最大布局次数,默认300
        force_node_repulsion: 1,
        force_line_elastic: 1
    }
})

// 定义默认的关系数据
const graphJsonData: RGJsonData = {
    rootId: 'root',
    nodes: [
        {
            id: 'root',
            text: '根节点',
            expanded: true,
            children: []
        }
    ],
    lines: []
}

onMounted(async () => {
    const graphInstance = relationGraphRef.value!.getInstance()

    // 停止自动布局
    await graphInstance.stopAutoLayout()

    // 渲染关系图
    await renderGraph(graphInstance)

    // 初始渲染后缩放设置为100%
    await graphInstance.setZoom(100)

    // 1.5s后自动将视图调整到充满画布
    resizeTimer.value = setInterval(async () => {
        const graphInstance = relationGraphRef.value!.getInstance()
        await graphInstance.zoomToFit()
    }, 1500)
})

onUnmounted(() => {
    clearInterval(resizeTimer.value)
})

// 渲染关系图
const renderGraph = async graphInstance => {
    await getGraphJsonList()
    await graphInstance.setJsonData(graphJsonData)
}

// 获取关系图数据
const getGraphJsonList = async () => {
    // 调接口获取关系图的节点数据(这里就用假数据代替了)
    const graphJsonList = [
        {
            id: 'a',
            name: 'a'
        },
        {
            id: 'b',
            name: 'b',
            children: [
                {
                    id: 'b1',
                    name: 'b1',
                    children: [
                        { id: 'b1-1', name: 'b1-1' },
                        { id: 'b1-2', name: 'b1-2' },
                        { id: 'b1-3', name: 'b1-3' },
                        { id: 'b1-4', name: 'b1-4' },
                        { id: 'b1-5', name: 'b1-5' },
                        { id: 'b1-6', name: 'b1-6' }
                    ]
                },
                {
                    id: 'b2',
                    name: 'b2',
                    children: [
                        { id: 'b2-1', name: 'b2-1' },
                        { id: 'b2-2', name: 'b2-2' }
                    ]
                }
            ]
        },
        {
            id: 'c',
            text: 'c',
            children: [
                { id: 'c1', name: 'c1' },
                { id: 'c2', name: 'c2' },
                { id: 'c3', name: 'c3' }
            ]
        }
    ]

    // 获取子节点数据
    const graphJsonDataNode = getChildNodeData(graphJsonList)
    // 添加子节点数据
    graphJsonData.nodes[0].children = graphJsonDataNode || []
}

// 获取子节点数据
const getChildNodeData = (list: any[]): any[] => {
    // 过滤掉无效的数据
    let newList = list.filter(item => item.name)

    // 递归遍历数据,指定要渲染前几层数据
    newList = extractLayers(newList, 3)

    // 添加子节点
    return newList.map((item: any) => {
        const row: any = {
            id: item.id,
            text: item.name,
            expanded: false
        }
        if (item.children && item.children[0]) {
            row.children = getChildNodeData(item.children)
        }
        return row
    })
}

/**
 * 递归遍历数据的指定前几层
 * @data 数据
 * @level 指定的层级
 * @currentLevel 当前层级
 */
const extractLayers = (data: any[], level: number, currentLevel = 1): any[] => {
    // 递归终止条件:如果当前层级大于指定层级,则不再递归
    if (currentLevel > level) {
        return []
    }

    return data.map(item => {
        // 复制当前节点
        const newItem = { ...item }

        // 如果当前节点有子节点,并且当前层级小于等于指定层级
        if (newItem.children) {
            // 递归处理子节点
            newItem.children = extractLayers(
                newItem.children,
                level,
                currentLevel + 1
            )
        } else {
            // 没有子节点时,确保删除 children 属性
            delete newItem.children
        }

        return newItem
    })
}

// 点击节点事件
const onNodeClick = (node: RGNode, e: RGUserEvent) => {
    // console.log('onNodeClick:', node.id)
    return true
}

// 点击线条事件
const onLineClick = (line: RGNode, e: RGUserEvent) => {
    // console.log('onLineClick:', line.id, '0000')
    return true
}

// 当节点拖动结束时
const onNodeDragEnd = (node: RGNode, e: RGUserEvent) => {}

// 节点展开事件处理函数
const onNodeExpand = async (node: RGNode, e: RGUserEvent) => {
    // console.log('onNodeExpand:', node.id)
    const graphInstance = relationGraphRef.value!.getInstance()

    // 在节点展开时,更新其状态
    node.expanded = true

    // 这里可以添加代码来处理展开节点的子节点数据

    // 开启自动布局
    await graphInstance.startAutoLayout()
}

// 节点收缩事件处理函数
const onNodeCollapse = async (node: RGNode, e: RGUserEvent) => {
    // console.log('onNodeCollapse:', node.id)
    const graphInstance = relationGraphRef.value!.getInstance()

    // 在节点收缩时,更新其状态
    node.expanded = false

    // 这里可以添加代码来处理收缩节点的子节点数据

    // 开启自动布局
    await graphInstance.startAutoLayout()
}
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值