实现效果如下图:
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=".g6-{$version}/build/g6.js"></script>// version >= 3.3
<script src="/{$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 = ElementById('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 = BBox();// 科目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 = BBox(); // 获取元素的包围盒/* 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 = Container();let mask = group.find(ele => ('name') === 'mask-shape');let maskLabel = group.find(ele => ('name') === 'mask-label-shape');('children').forEach(child => {if (('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 = Container();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 = ateElement('div');Align = 'left';const nodeName = Model().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 (('name') === 'name-shape' || ('name') === 'mask-label-shape') return true;const nodeName = Model().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);der();const handleCollapse = (e) => {const target = e.target;const id = ('modelId');const item = graph.findById(id);const nodeModel = Model();llapsed = !llapsed;graph.layout();graph.setItemState(item, 'collapse', llapsed);};('collapse-text:click', (e) => {handleCollapse(e);});('collapse-back:click', (e) => {handleCollapse(e);});};initGraph(data);if (typeof window !== 'undefined')size = () => {if (!graph || ('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 = ElementById("container").clientWidth;const con_Height = ElementById("container").clientHeight;// 重新计算画布中心的坐标const centerX = con_width / 2 - 60;const centerY = con_Height / 2 - 60;// 以 x, y 为坐标中心,进行缩放To(0.7, {x: centerX,y: centerY})
}
以上方法需在 der() 之前执行。
友情提示:新手小白入门的话最好是先找个和自己需求相似案例看看,然后开始照猫画虎,画着画着慢慢就能就看明白了,当然 大佬略过哈 ~ 多看看官方的文档,写的很详细。
本文发布于:2024-02-02 19:30:18,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170687341945948.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |