Antd G6实现自定义工具栏

在使用g6实现知识图谱可视化中,产品经理提出了有关图谱操作的不少功能,需要放置在工具栏中,其中有些功能不在g6自带的功能里,且工具栏样式、交互效果也和官方自定义工具栏不同。那我们怎么去实现呢?

g6官方的工具栏案例是这样:G6,提供了"重做","撤销","放大","缩小","适应屏幕","实际大小"的操作,配置项中也提供了有关样式及操作的回调功能,但是,远不能满足我们产品需要的样式及功能。

产品的需求中,工具栏各操作需要有激活和未激活的效果,悬浮的效果等等。操作除了官方工具栏自带的操作,还需"高亮","鱼眼放大镜","布局","下载","关系标签显隐"的功能。

那我们就给工具栏换个新包装吧!话不多说,看效果,上代码。

html 复制代码
<div v-if="graphState.showTool" class="toolbar">
            <a-tooltip title="展开/收起" color="geekblue" placement="right">
              <div class="inactiveTool">
                <MenuUnfoldOutlined
                  v-if="graphState.collapse"
                  style="font-size: 20px"
                  @click="
                    () => {
                      graphState.collapse = !graphState.collapse;
                    }
                  "
                />
                <MenuFoldOutlined
                  v-else
                  style="font-size: 20px"
                  @click="
                    () => {
                      graphState.collapse = !graphState.collapse;
                    }
                  "
                />
              </div>
            </a-tooltip>
            <a-space v-show="!graphState.collapse" direction="horizontal">
              <a-tooltip title="放大" color="geekblue" placement="right">
                <div
                  code="zoomOut"
                  :class="graphState.activeTool == 'zoomOut' ? 'activeTool' : 'inactiveTool'"
                >
                  <ZoomInOutlined @click="handleClickTool('zoomOut')" style="font-size: 20px" />
                </div>
              </a-tooltip>
              <a-tooltip title="缩小" color="geekblue" placement="right">
                <div
                  code="realZoom"
                  :class="graphState.activeTool == 'zoomIn' ? 'activeTool' : 'inactiveTool'"
                >
                  <ZoomOutOutlined @click="handleClickTool('zoomIn')" style="font-size: 20px" />
                </div>
              </a-tooltip>
              <a-tooltip title="自适应" color="geekblue" placement="right">
                <div :class="graphState.activeTool == 'realZoom' ? 'activeTool' : 'inactiveTool'">
                  <OneToOneOutlined @click="handleClickTool('realZoom')" style="font-size: 20px" />
                </div>
              </a-tooltip>
              <a-tooltip title="视图居中" color="geekblue" placement="right">
                <div
                  :class="graphState.activeTool == 'autoZoom' ? 'activeTool' : 'inactiveTool'"
                  style="font-size: 20px"
                >
                  <PicCenterOutlined @click="handleClickTool('autoZoom')" style="font-size: 20px" />
                </div>
              </a-tooltip>
              <a-tooltip title="高亮相邻节点" color="geekblue" placement="right">
                <div :class="graphState.activeTool == 'relation' ? 'activeTool' : 'inactiveTool'">
                  <DeploymentUnitOutlined
                    @click="handleClickTool('relation')"
                    style="font-size: 20px"
                  />
                </div>
              </a-tooltip>
              <a-tooltip title="鱼眼放大镜" color="geekblue" placement="right">
                <div :class="graphState.activeTool == 'fishEye' ? 'activeTool' : 'inactiveTool'">
                  <EyeOutlined @click="handleClickTool('fishEye')" style="font-size: 20px" />
                </div>
              </a-tooltip>
              <a-popover
                title="布局方案"
                placement="right"
                @visibleChange="handleChangeVisibleLayout"
              >
                <template #content>
                  <a-radio-group
                    v-model:value="graphState.layout.type"
                    @change="handleChangeLayout"
                  >
                    <div>
                      <a-radio value="AI" :disabled="graphState.nodes.length >= 100">
                        多边散列排布(少量数据推荐)
                      </a-radio>
                    </div>
                    <div>
                      <a-radio value="gForce">gForce力导向布局</a-radio>
                    </div>
                    <div>
                      <a-radio value="force2">基础力导向布局</a-radio>
                    </div>
                    <div v-show="false">
                      <a-radio value="fruchterman">Fruchterman布局</a-radio>
                    </div>
                  </a-radio-group>
                </template>
                <div :class="graphState.activeTool == 'layout' ? 'activeTool' : 'inactiveTool'">
                  <LayoutOutlined style="font-size: 20px" />
                </div>
              </a-popover>
              <a-tooltip title="导出图片" color="geekblue" placement="right">
                <div :class="graphState.activeTool == 'download' ? 'activeTool' : 'inactiveTool'">
                  <DownloadOutlined @click="handleClickTool('download')" style="font-size: 20px" />
                </div>
              </a-tooltip>
              <a-tooltip title="关系标签显隐" color="geekblue" placement="right">
                <div
                  :class="
                    graphState.activeTool == 'relationVisible' ? 'activeTool' : 'inactiveTool'
                  "
                >
                  <ArrowRightOutlined
                    @click="handleClickTool('relationVisible')"
                    style="font-size: 20px"
                  />
                </div>
              </a-tooltip>
            </a-space>
          </div>

上述代码中,我们根据业务需求做了工具栏整体的显示隐藏,展开收起,关系显隐,图片下载等功能。工具栏面板我们可以根据自己系统使用的组件库,ant design 、element ui或者其他。添加图标,提示框,选中等效果。这里不多赘述。

那么,怎么将g6的功能添加到我们工具栏上面使用呢?

我们定义了一组响应式对象,用来存储当前激活的工具或效果。

javascript 复制代码
const graphState = reactive({
      layout: {
        type: 'force2',
        advanceWeight: false,
        damping: 0.8,
        kr: 1000,
        preset: {
          minNodeSpacing: 10,
          nodeSize: 10,
          type: 'concentric',
        },
        clustering: true,
        animate: false,
        preventOverlap: true,
        clusterNodeStrength: 35,
        distanceThresholdMode: 'max',
        minMovement: 10,
        maxSpeed: 1000,
        linkDistance: 50,
        edgeStrength: 200,
        nodeStrength: 1000,
        nodeWeightFieldScale: 1,
        nodeWeightFromType: 'node',
        fitCenter: true,
      },
      showTool: false,
      activeTool: '',  //当前激活的工具
      enableFishEye: false, //是否启用鱼眼放大镜
      relation: false, //是否开启高亮相邻节点
      enableLegend: false, //是否开启图例
      relationVisible: true, //关系标签显示隐藏
      collapse: false,  //展开或折叠工具栏
    });

引入G6,定义graph,用来初始化G6实例,再初始化G6的工具栏

javascript 复制代码
import G6 from '@antv/g6';
javascript 复制代码
let graph;
let toolbar = new G6.ToolBar({
      className: 'g6-component-toolbar',
    });

通过动态的给graph 实例添加插件、添加行为动作,达到调用工具栏功能的目的。

javascript 复制代码
const handleClickTool = code => {
      if (toolbar.destroyed) {
        toolbar = new G6.ToolBar({
          className: 'g6-component-toolbar',
        });
        graph.addPlugin(toolbar);
      }
      if (code === 'zoomOut') {
        toolbar.zoomOut();
        //...
      } else if (code === 'zoomIn') {
        toolbar.zoomIn();
       //...
      } 
      //...
      graph.fitCenter();
      graphState.activeTool = code;
    };

其他功能实现读者可查询G6官网API自行实现。这里只简述思路和原理。

相关推荐
mldong4 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排4 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60615 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角6 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!6 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰6 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi8 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen8 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马9 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒9 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端