使用antv-F6进行uniapp,小程序树状图绘制

1,474 阅读3分钟
  • 前言

近期有一个项目需求,需要在使用uniapp在小程序端进行树状图的绘制,并且能够点击跳转。 需求并不难,在掘金也很快找到了对应的框架——antv-F6)。 如何在小程序绘制树状图

这篇文章已经把小程序的使用示例说得很清楚了,且文章末尾附上了gitbub地址及文档地址,虽然没在文章中写出来,但能找到对应的uniapp示例 uniapp示例(antv-F6) antv-F6文档

下面是我在uniapp中参考官方示例项目进行引入的参考。

1、到antv-F6的uniapp示例中下载如图两个文件夹,分别为示例组件canvas和antv-F6的源码

image.png

2、在自己的uniapp项目中,创建components文件夹,粘贴所下载的源码,可删除.map文件

image.png

3、创建页面,在页面中引入和使用 关于所需样式的问题,可以查看antv-F6的文档,建议先选择好想要的图的类型,再进行样式和交互的调整。树状图要比普通的图多引入一个treeGraph,文档里没有示例,要自己注意下。 如果有一些不明白的且实在找不到的样式属性,不妨参考下G6的文档(我就是这么干的😭)。

效果图:

微信图片_20230927164736.png

页面示例代码如下:

<template>
    <f6-canvas :width="width" :height="height" :pixelRatio="pixelRatio" @onInit="onCanvasInit" @onTouchEvent="onTouchEvent"/>
</template>
<script>
  import F6Canvas from '@/components/antv-F6/canvas/canvas.vue';
	import F6 from '@/components/antv-F6/f6';
	import TreeGraph from '@/components/antv-F6/f6/extends/graph/treeGraph';
  export default {
		name: "chainTree",
		props: {},
		components: {
			'f6-canvas': F6Canvas,
		},
          created() {
                    F6.registerGraph('TreeGraph', TreeGraph);
		},
          methods: {
			//打开产业选择框
			openSelect() {
				this.show = true
			},
			//产业选择框确认事件
			confirm(e) {
				this.show = false
				this.selectValue = e.value[0].label
			},
			onTouchEvent(e) {
				this.graph && this.graph.emitEvent(e);
			},
			onCanvasInit({
				ctx,
				rect,
				container,
				renderer
			}) {
				// console.log('canvas init ready', ctx, rect, container, renderer);
				const {
					width,
					height,
					pixelRatio
				} = this;
				this.graph = new F6.TreeGraph({
					container: container,
					context: ctx,
					renderer,
					width,
					height,
					pixelRatio,
					fitView: true,
					layout: {
						type: 'compactBox',
						direction: 'TB', // H / V / LR / RL / TB / BT
						getId: function getId(d) {
							return d.id;
						},
						getHeight: function getHeight() {
							return 85;
						},
						getWidth: function getWidth() {
							return 50;
						},
						//每个节点的垂直间隙
						getVGap: function getVGap() {
							return 10;
						},
						//每个节点的水平间隙
						getHGap: function getHGap() {
							return 16;
						},

					},
					//统一配置节点样式
					defaultNode: {
						type: 'rect', 
						//矩形宽高
						size: [75, 40],
						style: {
							fill: '#fff',
							// lineWidth: 1,
							stroke: '#fff',
							radius: 10
						},
						//节点连接点样式
						linkPoints: {
							top: true,
							fill: '#fff',
							stroke: '#364c6b'
						},
					},
					//边样式
					defaultEdge: {
						style: {
							stroke: '#364c6b',
							lineWidth: 1,
						}
					},
					nodeStateStyles: {
						//被选择节点样式
						tap: {
							fill: '#25b3f9',
							lineWidth: 0,
							'text-shape': {
								fill: "#ffffff"
							}
						},

					},
					modes: {
						default: ['drag-canvas', 'zoom-canvas']
					},
				});
				const anchorPoints = [
					[0.5, 0],
					[0.5, 1]
				]
				const data = {
					id: 'node-main', // String,该节点存在则必须,节点的唯一标识
					size: [120, 30],
					x: 150, // Number,可选,节点位置的 x 值
					y: 200, // Number,可选,节点位置的 y 值
					type: 'rect',
					label: '光电子信息',
					anchorPoints: anchorPoints,
					style: {
						stroke: '#e2e2e2',
						lineWidth: 2
					},
					labelCfg: {
						style: {
							fontWeight: 500,
							fontSize: 16,
						},
					},
					linkPoints: {
						top: false,
						bottom: true
					},
					children: [{
							id: 'node1-1', // String,该节点存在则必须,节点的唯一标识
							label: '数据驱动',
							anchorPoints: anchorPoints,
							children: [{
									id: 'node1-2',
									label: '网络化',
									anchorPoints: anchorPoints,
									children: [{
											id: 'node1-3',
											label: '电话通信网',
											anchorPoints: anchorPoints
										},

									],
								},

							],
						},
						{
							id: 'node2-1',
							label: '支撑要素',
							anchorPoints: anchorPoints,
							children: [{
									id: 'node2-2',
									label: '数字化',
									anchorPoints: anchorPoints,
								},

							],
						},

					],
				};
				const graph = this.graph
				graph.data(data);
				graph.render();
				graph.on('node:tap', (evt) => {
					const node = evt.item;
					const hasActived = node._cfg.states.length;

					// 当节点没有被点击过时
					if (hasActived == 0) {
						// 激活该节点的 tap状态
						graph.setItemState(node, 'tap', true);
						//点击后跳转,根节点不跳转
						if (node._cfg.id != "node-main") {
							setTimeout(() => {
								graph.setItemState(node, 'tap', false);
							}, 500)
						}
					} else {
						graph.setItemState(node, 'tap', false);
					}
				});
				graph.fitView();
			}
		},
                
     }
</script>