JavaScript is required

班级兴趣小组示意图

兴趣小组互动映射与画布插槽

使用自定义画布插槽和连接目标可视化兴趣小组与成员之间的关系,支持动态高亮和背景地图叠加。

功能概述

此示例展示了如何使用自定义画布插槽创建兴趣小组和班级成员之间的关系可视化。通过 RGSlotOnCanvasRGConnectTarget 组件,可以在画布上任意位置放置自定义 UI 元素,并自动处理与这些元素的连接线。当点击兴趣小组时,高亮显示加入该小组的成员;当点击成员时,高亮显示该成员加入的所有兴趣小组。

核心特性实现

画布插槽渲染

使用 RGSlotOnCanvas 在画布上添加自定义元素:

<RelationGraph options={graphOptions}>
    <RGSlotOnCanvas>
        <div style={{ zIndex: 2, position: 'absolute', left: -700, top: 100 }}>
            {interestGroups.map(group => (
                <div key={group.groupId} style={{ left: group.location.x + 'px', top: group.location.y + 'px' }}>
                    {/* 自定义兴趣小组标记 */}
                </div>
            ))}
        </div>
    </RGSlotOnCanvas>
</RelationGraph>

这允许在画布的任意坐标放置 UI 元素。

连接目标组件

使用 RGConnectTarget 使自定义元素可连接:

<RGConnectTarget
    targetId={`group-${group.groupId}`}
    junctionPoint={RGJunctionPoint.lr}
    disableDrag={true}
    disableDrop={true}
>
    <div className="c-i-group" onClick={() => onGroupClick(group.groupId)}>
        <div className="c-i-name">{group.groupName}</div>
    </div>
</RGConnectTarget>

RGConnectTarget 充当虚拟节点,可以与其他节点或连接目标建立连接。

动态关系线创建

根据选中的小组或成员动态创建连接线:

const updateMyLines = async () => {
    await graphInstance.sleep(100);
    const myFakeLines = [];

    if (activeGroupId) {
        // 显示该小组的所有成员
        classMembers.forEach((member, index) => {
            if (member.joinedGroups.includes(activeGroupId)) {
                myFakeLines.push({
                    id: `line-member-${index}`,
                    from: 'member-' + member.name,
                    to: 'group-' + activeGroupId,
                    color: 'rgba(29,169,245,0.76)',
                    lineShape: RGLineShape.StandardCurve
                });
            }
        });
        // 添加从小组到位置的连接线
        myFakeLines.push({
            id: `line-group-loc-${activeGroupId}`,
            from: 'group-' + activeGroupId,
            to: 'location-' + activeGroupId,
            color: 'rgba(159,23,227,0.65)',
            lineWidth: 3,
            lineShape: RGLineShape.StandardCurve,
            animation: 2
        });
    }

    graphInstance.clearGraph();
    graphInstance.addNodes([{ id: 'fake-root', text: '', opacity: 0, x: 0, y: 0 }]);
    graphInstance.addFakeLines(myFakeLines);
};

每次选择改变时,重新计算并渲染关系线。

背景地图叠加

在画布上添加背景图片:

<div style={{ zIndex: 1, position: 'absolute', left: -700, top: 100 }}>
    <img
        src={`https://www.relation-graph.com/images/school-map.png`}
        style={{ width: '100%', pointerEvents: 'none' }}
    />
</div>

背景图片提供地理上下文,使可视化更加直观。

状态管理

使用 React 状态管理当前选中的小组和成员:

const [activeGroupId, setActiveGroupId] = React.useState('');
const [activeMemberName, setActiveMemberName] = React.useState('');

const onGroupClick = async (groupId: string) => {
    setActiveGroupId(groupId);
    setActiveMemberName('');
};

const onMemberClick = (memberName: string) => {
    setActiveGroupId('');
    setActiveMemberName(memberName);
};

确保同一时间只显示一种类型的关系。

响应式更新

使用 useEffect 监听状态变化并更新连接线:

useEffect(() => {
    updateMyLines();
}, [activeGroupId, activeMemberName]);

每当选择改变时自动重新渲染关系线。

Z-index 层级控制

使用不同的 z-index 值控制元素层级:

<div style={{ zIndex: 1 }}> {/* 背景地图 */}</div>
<div style={{ zIndex: 2 }}> {/* 地图上的位置标记 */}</div>
<div style={{ zIndex: 10 }}> {/* 兴趣小组列表 */}</div>
<div style={{ zIndex: 20 }}> {/* 成员列表 */}</div>

确保 UI 元素按正确的顺序叠加。

创意使用场景

校园设施导航

创建校园地图应用,显示教学楼、食堂、图书馆等设施,并显示学生与设施的关系。点击设施显示正在使用的学生,点击学生显示其常去的地方。

展位导航系统

用于展览或会议的展位导航,显示参展商位置和参观者的兴趣匹配。点击展位显示感兴趣的参观者,帮助业务对接。

社交活动匹配

在社交活动中展示参与者和兴趣小组的匹配关系。帮助参与者找到志同道合的人,促进交流。

资源分配可视化

展示办公室、会议室、工位等资源与员工的关系。点击资源查看使用人,点击员工查看其使用的所有资源。

服务网络可视化

展示服务中心、服务点与客户的位置关系。帮助优化服务覆盖和资源配置。

智能家居控制

在户型图上显示智能设备和房间的关系。点击设备查看所在房间,点击房间查看所有设备。

物流配送网络

展示配送站、包裹和配送员的关系。优化配送路线和资源分配。

零售店布局分析

在商店平面图上显示商品类别和顾客购物篮的关系。分析顾客行为和商品关联。

紧急疏散规划

显示建筑出口、安全区域和人员位置的关系。帮助制定紧急疏散方案。

旅游景点推荐

在地图上显示景点和游客兴趣的关系。提供个性化旅游推荐。