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 等布局框架实现自定义效果。
相关推荐
百万蹄蹄向前冲1 分钟前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳58139 分钟前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路1 小时前
GeoTools 读取影像元数据
前端
ssshooter1 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry2 小时前
Jetpack Compose 中的状态
前端
dae bal3 小时前
关于RSA和AES加密
前端·vue.js
柳杉3 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog3 小时前
低端设备加载webp ANR
前端·算法
LKAI.3 小时前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi
刺客-Andy4 小时前
React 第七十节 Router中matchRoutes的使用详解及注意事项
前端·javascript·react.js