antv/g6 绘制生态图-新手入门

2023-12-14 13:59

本文主要是介绍antv/g6 绘制生态图-新手入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实现效果如下图:

 API文档:图配置 G6.Graph(cfg) | G6

参考样例:自定义树图 | G6

 坐标转换:坐标转换

一、安装 & 引用

1. 通过npm包引入

npm install --save @antv/g6

   在需要使用的文件中直接引入G6即可

import G6 from "@antv/g6"

2. 通过CDN形式引入

// version <= 3.2
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-{$version}/build/g6.js"></script>// version >= 3.3
<script src="https://gw.alipayobjects.com/os/lib/antv/g6/{$version}/dist/g6.min.js"></script>

二、数据结构如下:

const mockData = {id: 'g1',name: '我是科目我是科目我是科目我是科目我是科目我是科目目目目目',dataType: 'root',amount: 123123213123.123123,children: [{id: 'g12',name: 'Deal with LONG label LONG label LONG label LONG label',amount: 123123213123.123123,children: [{id: 'g121',name: 'Name3',collapsed: true,amount: 123123213123.123123,children: [{id: 'g1211',name: 'Name4',amount: 123123213123.123123,children: [],},],},{id: 'g122',name: 'Name5',collapsed: true,amount: 2.34,children: [{id: 'g1221',name: 'Name6',amount: 0.123123,children: [{id: 'g12211',name: 'Name6-1',amount: 123123,children: [],},],},{id: 'g1222',name: 'Name7',amount: 123123213123.123123,children: [],},],},{id: 'g123',name: 'Name8',collapsed: true,amount: 12,children: [{id: 'g1231',name: 'Name8-1',amount: 123123213123.123123,children: [],},],},],},{id: 'g13',name: 'Name9',amount: 123123213123.123123,children: [{id: 'g131',name: 'Name10',amount: 12313123.123123,children: [],},{id: 'g132',name: 'Name11',amount: 123123213123.123123,children: [],},],},{id: 'g14',name: 'Name12',amount: 123123213123.123123,children: [],},],};

完整代码如下:

<template><div id="container"></div>
</template><script>
import G6 from '@antv/g6';export default {name: 'HelloWorld',props: {msg: String},created() { },mounted() {this.initAntv();},methods: {// 初始化initAntv() {//  组件propsconst props = {data: mockData,config: {padding: [20, 50],// defaultLevel: 3,defaultZoom: 0.8,modes: { default: ['zoom-canvas', 'drag-canvas'] },},};const container = document.getElementById('container');const width = container.scrollWidth;const height = container.scrollHeight || 500;// 默认配置const defaultConfig = {width,height,modes: {default: ['zoom-canvas', 'drag-canvas'],},fitView: true,animate: true,minZoom: 0.5,maxZoom: 1.5,linkCenter: false,defaultNode: {  // 默认节点type: 'flow-rect',},defaultEdge: {  // 默认边type: 'cubic-horizontal',style: {stroke: 'rgb(93, 162, 216)',},},layout: {  // layout 布局配置type: 'mindmap', direction: 'V',dropCap: false,rankSep: 350,nodeSep: 100,getHeight: () => {return 60;},// 节点横向间距的回调函数getHGap: function getHGap() {return 150;}},};// 自定义节点const registerFn = () => {/*** 自定义节点*/G6.registerNode('flow-rect',{shapeType: 'flow-rect',draw(cfg, group) {const {name = '',collapsed,dataType,amount,} = cfg;const config = {basicColor: 'rgb(66, 151, 215)',  // 左边粗线的颜色fontColor: 'rgb(74, 177, 241)',  // 字体颜色borderColor: 'rgb(169, 217, 252)', // 边框颜色bgColor: 'rgb(230, 240, 250)',  // 矩形背景色};const rectConfig = {width: 243,height: 64,lineWidth: 1,fontSize: 12,opacity: 1,fill: config.bgColor,stroke: config.borderColor,radius: 2,cursor: 'pointer',};const nodeOrigin = {x: -rectConfig.width / 2,y: -rectConfig.height / 2,};const textConfig = {textAlign: 'left',textBaseline: 'bottom',};if (dataType != 'root') {/* 左边的小圆点 */group.addShape('circle', {attrs: {x: nodeOrigin.x - 0,y: 0,r: 6,fill: config.basicColor,},name: 'left-dot-shape',});}// 外层矩形const rect = group.addShape('rect', {attrs: {x: nodeOrigin.x,y: nodeOrigin.y,...rectConfig,},});/* 左边的粗线 */group.addShape('rect', {attrs: {x: nodeOrigin.x,y: nodeOrigin.y,width: 3,height: rectConfig.height,fill: config.basicColor,radius: 1.5,},name: 'left-border-shape',});const rectBBox = rect.getBBox();// 科目group.addShape('text', {attrs: {...textConfig,x: 12 + nodeOrigin.x,y: 20 + nodeOrigin.y,text: name.length > 16 ? name.substr(0, 16) + '...' : name,fontSize: 12,opacity: 0.85,fill: config.fontColor,cursor: 'pointer',},name: 'name-shape',});if (amount) {// 金额-矩形const amountRect = group.addShape('rect', {attrs: {fill: '#fff',radius: 2,stroke: config.borderColor,cursor: 'pointer', // 需要调整},name: 'amount-container-shape',})// 金额const amountText = group.addShape('text', {attrs: {...textConfig,x: rectBBox.maxX - 10,y: rectBBox.maxY - 10,text: `${amount}`,fontSize: 12,textAlign: 'right',fill: '#000',},name: 'amount-text-shape',});const amountBBox = amountText.getBBox(); // 获取元素的包围盒/* amountBBox */amountRect.attr({x: rectBBox.maxX - amountBBox.width - 15,y: rectBBox.maxY - 27,width: amountBBox.width + 10,height: amountBBox.height + 10,});}// collapse rectif (cfg.children && cfg.children.length) {group.addShape('circle', {attrs: {x: rectConfig.width / 2 + 8.5,y: 0,r: 8,width: 16,height: 16,stroke: 'rgb(74, 177, 241)',cursor: 'pointer',fill: '#fff',},name: 'collapse-back',modelId: cfg.id,});// collpase textgroup.addShape('text', {attrs: {x: rectConfig.width / 2 + 8.5,y: 1,textAlign: 'center',textBaseline: 'middle',text: collapsed ? '+' : '-',fontSize: 16,cursor: 'pointer',fill: 'rgb(74, 177, 241)',},name: 'collapse-text',modelId: cfg.id,});}return rect;},update(item) {// const { level, name } = cfg;// console.log("update生命周期函数中的cfg========", cfg)const group = item.getContainer();let mask = group.find(ele => ele.get('name') === 'mask-shape');let maskLabel = group.find(ele => ele.get('name') === 'mask-label-shape');group.get('children').forEach(child => {if (child.get('name')?.includes('collapse')) return;child.show();})mask?.animate({ opacity: 0 }, {duration: 200,callback: () => mask.hide()});maskLabel?.animate({ opacity: 0 }, {duration: 200,callback: () => maskLabel.hide()});},setState(name, value, item) {if (name === 'collapse') {const group = item.getContainer();const collapseText = group.find((e) => e.get('name') === 'collapse-text');if (collapseText) {if (!value) {collapseText.attr({text: '-',});} else {collapseText.attr({text: '+',});}}}},getAnchorPoints() {return [[0, 0.5],[1, 0.5],];},},'rect',);};registerFn();const { data } = props;let graph = null;const initGraph = (data) => {if (!data) {return;}const { onInit, config } = props;const tooltip = new G6.Tooltip({// offsetX and offsetY include the padding of the parent containeroffsetX: 20,offsetY: 30,// 允许出现 tooltip 的 item 类型itemTypes: ['node'],// custom the tooltip's content// 自定义 tooltip 内容getContent: (e) => {const outDiv = document.createElement('div');outDiv.style.textAlign = 'left';const nodeName = e.item.getModel().name;let formatedNodeName = '';for (let i = 0; i < nodeName.length; i++) {formatedNodeName = `${formatedNodeName}${nodeName[i]}`;if (i !== 0 && i % 20 === 0) formatedNodeName = `${formatedNodeName}<br/>`;}outDiv.innerHTML = `${formatedNodeName}`;return outDiv;},shouldBegin: (e) => {// if (e.target.get('name') === 'name-shape' || e.target.get('name') === 'mask-label-shape') return true;const nodeName = e.item.getModel().name;if (nodeName.length > 24) {return true} else {return false;}},});graph = new G6.TreeGraph({container: 'container',...defaultConfig,...config,plugins: [tooltip],});if (typeof onInit === 'function') {onInit(graph);}graph.data(data);graph.render();const handleCollapse = (e) => {const target = e.target;const id = target.get('modelId');const item = graph.findById(id);const nodeModel = item.getModel();nodeModel.collapsed = !nodeModel.collapsed;graph.layout();graph.setItemState(item, 'collapse', nodeModel.collapsed);};graph.on('collapse-text:click', (e) => {handleCollapse(e);});graph.on('collapse-back:click', (e) => {handleCollapse(e);});};initGraph(data);if (typeof window !== 'undefined')window.onresize = () => {if (!graph || graph.get('destroyed')) return;if (!container || !container.scrollWidth || !container.scrollHeight) return;graph.changeSize(container.scrollWidth, container.scrollHeight);};}}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>

问题:

当我们按照以上操作绘制完图之后,发现画布中的内容并非居中展示,设置 fitView: true 并没有起作用,有可能是因为布局原因,有定位的设置可能会影响画布的中心坐标,有了解决问题的思路 ,我们就开始着手试试把。增加以下代码:

// 设置画布居中
setCenetr(graph) {const con_width = document.getElementById("container").clientWidth;const con_Height = document.getElementById("container").clientHeight;// 重新计算画布中心的坐标const centerX = con_width / 2 - 60;const centerY = con_Height / 2 - 60;// 以 x, y 为坐标中心,进行缩放graph.zoomTo(0.7, {x: centerX,y: centerY})
}

以上方法需在 graph.render() 之前执行。

友情提示:新手小白入门的话最好是先找个和自己需求相似案例看看,然后开始照猫画虎,画着画着慢慢就能就看明白了,当然 大佬略过哈 ~  多看看官方的文档,写的很详细。

这篇关于antv/g6 绘制生态图-新手入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/492798

相关文章

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

从去中心化到智能化:Web3如何与AI共同塑造数字生态

在数字时代的演进中,Web3和人工智能(AI)正成为塑造未来互联网的两大核心力量。Web3的去中心化理念与AI的智能化技术,正相互交织,共同推动数字生态的变革。本文将探讨Web3与AI的融合如何改变数字世界,并展望这一新兴组合如何重塑我们的在线体验。 Web3的去中心化愿景 Web3代表了互联网的第三代发展,它基于去中心化的区块链技术,旨在创建一个开放、透明且用户主导的数字生态。不同于传统

【WebGPU Unleashed】1.1 绘制三角形

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123 在 3D 渲染领域,三角形是最基本的绘制元素。在这里,我们将学习如何绘制单个三角形。接下来我们将制作一个简单的着色器来定义三角形内的像素

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87

YOLOv8/v10+DeepSORT多目标车辆跟踪(车辆检测/跟踪/车辆计数/测速/禁停区域/绘制进出线/绘制禁停区域/车道车辆统计)

01:YOLOv8 + DeepSort 车辆跟踪 该项目利用YOLOv8作为目标检测模型,DeepSort用于多目标跟踪。YOLOv8负责从视频帧中检测出车辆的位置,而DeepSort则负责关联这些检测结果,从而实现车辆的持续跟踪。这种组合使得系统能够在视频流中准确地识别并跟随特定车辆。 02:YOLOv8 + DeepSort 车辆跟踪 + 任意绘制进出线 在此基础上增加了用户