ant-G6 使用vue组件自定义节点

前言

依稀记得很久之前,用 ant-G6 开发了公司业务系统中的血缘视图。但是 ant-G6 却不能使用 当前流行的框架来实现自定义节点,这很大程度上限制了开发的可行性。最初我使用 提供的 rect,circle,image 等来实现业务效果。后来对 Vue 的了解上,发现并实践出了以下方法。

核心解决方案

本质上是使用 vue 的 render 渲染函数 和 h 函数,将vue的组件渲染为html,最终截取出来作为 G6 的节点使用。

自定义节点组件

xml 复制代码
// Node.vue

<template>
  <div
    :class="[$style['node'], isCenter ? $style['is-center'] : '']"
    role="button"
  >
    <ElIcon :class="$style['icon']" class="yg-icon mx-4">
      <component :is="icons['ai-search']"></component>
    </ElIcon>
    <span :class="$style['title']">{{ title || '' }}</span>
  </div>
</template>

<script lang="ts" setup>
// 自己封装导出图标,修改后使用
import icons from './icons';
// 
import { ElIcon } from '@element-plus';

const props = withDefaults(
  defineProps<{ isCenter?: boolean; title?: string }>(),
  {
    isCenter: true,
    title: '',
  }
);
</script>

<style lang="scss" module>
@use '@insight/ui/scss/config' as *;
@use '@insight/ui/scss/mixins' as *;
.node {
  height: 40px;
  width: 180px;
  display: flex;
  align-items: center;
  user-select: none;
  // background-color: var(--el-color-primary-light-5);
  background-color: #e4f0fa;
  color: var(--el-content-text-color-default);

  &.is-center {
    // background-color: var(--el-color-primary-light-3);
    background-color: rgb(22, 135, 232);
    color: var(--el-color-white);
  }

  &::before {
    content: '';
    width: 2px;
    height: 100%;
    background-color: var(--el-color-primary);
  }
}

.icon {
  color: var(--el-color-primary);
}

.title {
  display: inline-block;
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
</style>

Vue 组件转化为Html的 hooks

ini 复制代码
// index.ts

/**
 * Vue组件转换为Html字符串 hooks
**/
const useComponentHtmlString = () => {
  const $iconContainer = document.createElement('div');

  const getCustomNodeHtml = (
    nodeProps?: Partial<InstanceType<typeof Node>>
  ) => {
    render(vueH(Node, nodeProps), $iconContainer);
    return $iconContainer.innerHTML;
  };

  return {
    getCustomNodeHtml,
  };
};

使用

php 复制代码
registerNodeimport G6, {
  type GraphData,
  type NodeConfig,
  type ComboConfig,
  Graph,
  type INode,
  type IEdge,
  type Item,
} from '@antv/g6';


const { getCustomNodeHtml } = useComponentHtmlString();

自定义节点方法
G6.registerNode(
    'card-node',
    {
      draw: function drawShape(cfg, group) {
        // cfg 参数中包含节点的配置信息
        const rect = cfg.rect as Rect;
        const { width: w, height: h } = cfg.rect as Rect;
        const isField = rect.isField || false;
        const isCenter = rect.isCenter || false;
        const displayName = cfg.displayName as string;

        group.addShape('dom', {
          zIndex: 9,
          attrs: {
            height: 40,
            width: 180,
            x: 0,
            y: 0,
            opacity: 1,
            html: getCustomNodeHtml({ title: displayName, isCenter: isCenter }),
            cursor: 'pointer',
          },
          draggable: true,
          name: 'card-node',
        });

        group.addShape('rect', {
          zIndex: 1,
          attrs: {
            x: 0,
            y: 0,
            height: 40,
            width: 180,
            fill: 'transparent',
            opacity: 1,
            stroke: '',
          },
          name: 'rect-shape-border',
        });

        const shape = group.addShape('rect', {
          zIndex: 1,
          attrs: {
            height: 40,
            width: 180,
            x: 0,
            y: 0,
            fill: 'transparent',
            opacity: 1,
          },
          name: 'card-node-header-drag',
          draggable: true,
        });
        
        // more ...
        
        return shape
      }
    }
  )

注意点

  1. 虽然使用渲染函数可以实现自定义节点,和复杂的交互功能,但是一些节点的交互和自定义状态需要配合 ant-G6 的 nodeStateStyles 等等参数使用。
  2. 在 registerNode 的 draw 方法中,第一个参数 cfg 也包含了自定义节点配置的相关信息,可以基于 节点的dom 和rect 等布局框架实现自定义效果。
相关推荐
用户059540174462 小时前
把AI对话记忆存储测试从手工改成Playwright+pytest,覆盖率从20%提到96%,回归时间缩短90%
前端·css
kyriewen2 小时前
别再这样写TypeScript了——Code Review中最常见的8个反模式
前端·javascript·typescript
名字还没想好☜2 小时前
Next.js ‘use client‘ 到底加在哪:Server/Client Components 边界与常见报错
开发语言·前端·javascript·react·next.js
午安~婉3 小时前
GitHub Token/ GitHub Stats统计显示图异常
前端·github·vercel·github token
码云之上3 小时前
AI Agent 工程化总览篇:从 Prompt 到 Harness
前端·人工智能
2501_926978333 小时前
以说明书 DNA 为模板——完整 AGI 的结构图景
前端·人工智能·经验分享·笔记·ai写作
IT_陈寒3 小时前
Vite静态资源引用这个坑我踩得有点疼
前端·人工智能·后端
程序员黑豆4 小时前
鸿蒙应用开发:AttributeModifier 使用教程
前端·harmonyos
codeniu4 小时前
TRAE Work 实战 | 从"有个想法"到线上Demo,我全程只靠对话就完成了
前端·trae
妙码生花4 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十):增加管理员角色组管理
前端·后端·ai编程