Antd Charts 组织架构图 && 指标拆解图

image.png

-   开箱即用:默认呈现高质量图表,将对开发体验及用户体验的研究沉淀入图表的默认配置项
-   易于配置:用户能够根据具体业务需要较为轻松的调整图表细节
-   体验良好:视觉和交互体验聚焦于如何能够**展示和发现信息**"这一图表本源的职能上


它的文档是真的少。。。。。需要自己花时间研究。。。。。。。
1.根据数据层级关系,以树级的形式展开
2.支持一键展开,一键收起;
3.根据自己的UI,个性化设计


...类似于下面这种需求

image.png

存在的问题

1.整个图表,根据你传输的数据进行渲染

2.每个节点的折叠与展开

3.每个节点的样式自定义问题

4.特定的一键展开与一键收起

下面我们一个个来解决

核心API简化

  • 节点无法收起与展开

image.png

markerCfg:{
        show: true,
    },
markerCfg: (cfg) => {
      return {
        position: 'right',
        show: cfg.children?.length,
        style: (arg) => {
          return {
            stroke: arg.value.percent > 0.3 ? stroke : '#1f8fff',
          };
        },
      };
    },
  • 节点自定义—一般是避免不了!!!

支持单节点添加多内容,不止三个,通过group!.addShape(‘text’, {…})

customContent: (item, group, cfg) => {
    const { startX, startY, width } = cfg;
    const { text, value, icon } = item;
    let textShape, valueShape, iconShape; // 这里不止添加三个!!!
    
    textShape =
      text &&
      group!.addShape('text', {
        attrs: {
          textBaseline: 'top',
          x: startX,
          y: startY,
          text,
          fill: '#aaa',
        },
        // group 内唯一字段
        name: `text-${Math.random()}`,
      });
    valueShape =
      value &&
      group!.addShape('text', {
        attrs: {
          textBaseline: 'top',
          x: startX + width / 2,
          y: startY,
          text: value,
          fill: '#f00',
        },
        name: `value-${Math.random()}`,
      });
    iconShape =
      icon &&
      group!.addShape('image', {
        attrs: {
          x: startX,
          y: startY,
          width: 72,
          height: 72,
          img: icon,
        },
        name: `image-${Math.random()}`,
      });
    return Math.max(
      textShape?.getBBox().height ?? 0,
      valueShape?.getBBox().height ?? 0,
      iconShape?.getBBox().height ?? 0,
    );
  },
##### 数据的转化

```后端数据格式
const fecth = {
    data:{
        id: '1',
        type: 0,
        count: 15,
        childList: [
            {},
            {},
            {}
        ]
        ....
    }
}
 // 按照组件类库的数据格式
 // 下面以指标拆解图的格式为例
 const { data = {} } = await fetchData()
 const handleTransformData = ( arr = [] ) => {
    const finnallyData =  arr?.map(item=>({
        // 我们想要的数据格式· 其实递归 === 套公式
        // 结构出来最美观、方便了...
        id: item?.id,
        value: {
        title: item?.nodeName,
            items: [
                {
                    type: item?.type,
                    count: item?.count
                }
            ]
        },
        children: handleTransformData(item?.childList) || null, // 核心一步
    }))
    
    return finnallyData
 }
  • 节点的配置
nodeCfg: {
      size: [140, 25],
      percent: {
        position: 'bottom',
        size: 4,
        style: (arg) => {
          return {
            radius: [0, 0, 0, 2],
            fill: arg.value.percent > 0.3 ? stroke : '#1f8fff',
          };
        },
      },
      items: {
        containerStyle: {
          fill: '#fff',
        },
        padding: 6,
        style: (cfg, group, type) => {
          const styles = {
            icon: {
              width: 12,
              height: 12,
            },
            value: {
              fill: '#f00',
            },
            text: {
              fill: '#aaa',
            },
          };
          return styles[type];
        },
      },
      nodeStateStyles: {
        hover: {
          lineWidth: 2,
        },
      },
      title: {
        containerStyle: {
          fill: 'transparent',
        },
        style: {
          fill: '#000',
          fontSize: 12,
        },
      },
      style: (arg) => {
        return {
          fill: '#fff',
          radius: 2,
          stroke: arg.value.percent > 0.3 ? stroke : '#1f8fff',
        };
      },
    },
  • 节点的起始点

image.png

  • 边的配置
edgeCfg: {
      label: {
        style: {
          fill: '#aaa',
          fontSize: 12,
          fillOpacity: 1,
        },
      },
      style: (edge) => {
        return {
          stroke: '#518AD3',
          strokeOpacity: 0.5,
        };
      },
      endArrow: {
        fill: '#518AD3',
      },
      edgeStateStyles: {
        hover: {
          strokeOpacity: 1,
        },
      },
    },
  • 交互方式
    根据意思:画布拖拽,节点拖拽,zoom-canvas我也不知道。。。
behaviors: ['drag-canvas', 'zoom-canvas', 'drag-node'],
  • 是否居中
 fitCenter: true
  • 是否自适应
 autoFit: true
  • 是否有动画
 animate: false

数据的处理

  • 后端接口支持

  • 后端数据返回的形式,一级一级的返回,或者是数据一把搂回来

  • 当接口数据一把返回给我们,我们如何控制显示层级,坑点!!!
    当如果采用的是组织架构图,那真是不好意思,人家类库还不支持控制层级,当然,你要相信Antd团队的创造力,多看文档不会让你失望。

指标拆解图的出现

image.png

看着样子确实差不多,但是里面可以配置的东西,可以说是完全不同!!!

通过文档案例以及API介绍

我们可以发现,指标拆解图支持异步加载控制层级显示,完美的解决我们的,一键展开、一键收起,支持单节点展开及异步加载数据功能

异步加载

image.png

const fetchData = () => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(
          [1, 2].map(() => ({
            id: 'A2' + Math.random().toString(),
            value: {
              title: '异步节点' + Math.random().toString(),
              items: [
                {
                  text: '595万',
                },
                {
                  text: '占比',
                  value: '50%',
                  icon: 'https://gw.alipayobjects.com/zos/antfincdn/iFh9X011qd/7797962c-04b6-4d67-9143-e9d05f9778bf.png',
                },
              ],
            },
          })),
        );
      }, 1000);
    });
  };

  const getChildren = async () => {
    const asyncData = await fetchData();
    return asyncData;
  };
  
   const config = {
    data,
    autoFit: false,
    nodeCfg: {
      getChildren,
    },
    markerCfg: (cfg) => {
      return {
        show: true,
      };
    },
    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-node'],
  };

控制层级显示

image.png

需求解决方案:

1.后端接口一把把所有的数据返回,前端通过level控制显示层级 (完成一键展开)
2.当时,我通过条件渲染的方法,也就是写了两个图表,因为即使通过 useState() 声明一个状态,也不起作用,这个图表默认展示两层 (完成一键收起)
3.点击单节点展开,由于后端一把数据已经返回,只是通过level控制显示层级,此处无需异步加载,即可

坑点记录

  1. 数据无法set进去!!!记得检测id是否存在重复问题,当时我的后端就是,没有id给我设置为null,我又好巧不巧 id: item?.id || "1",设置节点ID默认值,排查一上午,才发现这个问题,我的内心是无比的崩溃的…
  2. 图表的tooltip,在示例上设置,能正常显示,结果本地看不到,我的内心也是十分的崩溃,一开始真的无从下手去排查,过了一会发现,它有时闪那么一下,脑子一闪,我好像设置是他的节点事件 node:mouseenter,来试验人家的方法,忘记删掉了,记得删除!记得删除!记得删除!,不然就等着崩溃,脑子宕机。。。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYknJ1EY' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片