使用echarts画一个类似组织结构图的图表

昨天,写了一篇关于圆环进度条的博客(请移步:Vue/React圆环进度条),已经烦不胜烦,今天又遇到了需要展示类似公司的组织结构图的功能需求,要冒了!!!

这种需求,自己用div+css也是可以实现的,但是没有什么动画效果,我的css3又很差劲,而且项目中已经使用到了折线图、饼状图、柱状图之类的图表,用的还是百度的echarts,所以这个组织结构图之类的需求也就用了百度的echarts来实现了。

以前用echarts写折线图、柱状图、饼状图的较多,它的API还算比较熟悉,但是画组织结构这样的树状图就很苦逼了,没用过啊,而且设计给的树状图的展示效果跟echarts树状图的展示效果相去甚远,我滴孩,又得一通费时费力的研究,设计图如下:

如图所示,一个树节点中可能会有两种不同的背景色,还有两种不同的文字颜色,每个节点展示的还是圆角矩形。有同学说了,echarts有设置圆角的API啊,直接设置不就完事了。我想说的是,它是提供的有这样的API,但是按照正常的套路实现不了啊。

从图上还可以看到一个几乎实现不了的效果,就是连接每个节点之间的线的拐角处都是直角而不是平滑的,而且echarts没有给出可以设置拐角处是直角的API,只是给了一个curveness(API的描述是树图边的曲度),这玩意儿使用了之后,也还是实现不了的。

从网上查了资料,有人说可以修改echarts的源码,这种解决办法我不推荐,是因为在vue或react项目中,echarts是需要通过安装在package.json中的,如果是多人并行开发,那么别人安装的echarts就不是你修改后的echarts,这就是问题所在。

最后用echarts画出来的效果还是很不错的,唯一没有实现的就是连接每个节点的线的拐角处不是直角,有好的解决办法的,还望不吝赐教,谢谢!展示一下最终的成果:

说了那么多,还是上代码吧,该代码是基于vue的,如果要使用在react中,稍微修改一下就可以了。

组件tree.vue:

<template>
  <div :class="className" :style="{height:height,width:width}" />
</template>

<script>
import echarts from "echarts";
require("echarts/theme/macarons");
import { debounce } from "@/utils";

export default {
  props: {
    className: {
      type: String,
      default: "chart"
    },
    width: {
      type: String,
      default: "100%"
    },
    height: {
      type: String,
      default: "500px"
    },
    chartData: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      chart: null,
    };
  },
  watch: {
    chartData: {
      deep: true,
      handler(val) {
        this.setOptions(val);
      }
    }
  },
  mounted() {
    this.initChart();
    //是否需要自适应-加了防抖函数
    this.__resizeHandler = debounce(() => {
      if (this.chart) {
        this.chart.resize();
      }
    }, 100);
    window.addEventListener("resize", this.__resizeHandler);

    // 监听侧边栏的变化以实现自适应缩放
    const sidebarElm = document.getElementsByClassName("sidebar-container")[0];
    sidebarElm.addEventListener("transitionend", this.sidebarResizeHandler);
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    window.removeEventListener("resize", this.__resizeHandler);
    this.chart.dispose();
    this.chart = null;

    const sidebarElm = document.getElementsByClassName("sidebar-container")[0];
    sidebarElm.removeEventListener("transitionend", this.sidebarResizeHandler);
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$el, "macarons");
      this.setOptions(this.chartData);
    },
    setOptions(data) {
      this.chart.setOption({
        //提供数据视图、还原、下载的工具
        // toolbox: {
        //   show : true,
        //   feature : {
        //     mark : {show: true},
        //     dataView : {show: true, readOnly: false},
        //     restore : {show: true},
        //     saveAsImage : {show: true}
        //   }
        // },
        series: [
          {
            name: "统一授信视图",
            type: "tree",
            orient: "TB", //竖向或水平   TB代表竖向  LR代表水平
            top: '10%',
            initialTreeDepth: 10,  //树图初始展开的层级(深度)
            expandAndCollapse: false,   //点击节点时不收起子节点,default: true
            symbolSize: [135, 65],
            itemStyle: {
              color: 'transparent',
              borderWidth: 0,
            },
            lineStyle: {
              color: '#D5D5D5',
              width: 1,
              curveness: 1,
            },
            data: [data]
          }
        ]
      });
    },
    sidebarResizeHandler(e) {
      if (e.propertyName === "width") {
        this.__resizeHandler();
      }
    }
  }
};
</script>

使用tree.vue的方法:

<template>
    <tree :chartData="treeData" />
</template>

<script>
import tree from './tree';

export default {
  data() {
    return {
      treeData: {
        label: {
          backgroundColor: '#F4F4F4',
          borderRadius: [0, 0, 5, 5],
          formatter: [
            '{first|综合授信额度}',
            '{second|(CR20190912000013)\n获批金额:100\n币种:人民币}',
          ].join('\n'),
          rich: {
            first: {
              backgroundColor: '#078E34',
              color: '#fff',
              align: 'center',
              width: 135,
              height: 30,
              borderRadius: [5, 5, 0, 0],
            },
            second: {
              color: '#888',
              align: 'center',
              lineHeight: 17,
            },
          }
        },
        children: [
          {
            label: {
              formatter: [
                '{first|渠道额度}',
              ].join('\n'),
              rich: {
                first: {
                  backgroundColor: '#3AC082',
                  color: '#fff',
                  align: 'center',
                  width: 135,
                  height: 65,
                  borderRadius: 5,
                },
              }
            },
            children: [{
              label: {
                formatter: [
                  '{first|保理额度}',
                ].join('\n'),
                rich: {
                  first: {
                    backgroundColor: '#3AC082',
                    color: '#fff',
                    align: 'center',
                    width: 135,
                    height: 65,
                    borderRadius: 5,
                  },
                }
              },
              children: [{
                label: {
                  backgroundColor: '#F4F4F4',
                  borderRadius: [0, 0, 5, 5],
                  formatter: [
                    '{first|反向保理}',
                    '{second|(CR20190912000013)\n获批金额:100\n币种:人民币}',
                  ].join('\n'),
                  rich: {
                    first: {
                      backgroundColor: '#078E34',
                      color: '#fff',
                      align: 'center',
                      width: 135,
                      height: 30,
                      borderRadius: [5, 5, 0, 0],
                    },
                    second: {
                      color: '#888',
                      align: 'center',
                      lineHeight: 17,
                    },
                  }
                },
              }]
            }]
          },
          {
            label: {
              formatter: [
                '{first|担保/(乐)集团/其他额度}',
              ].join('\n'),
              rich: {
                first: {
                  backgroundColor: '#3AC082',
                  color: '#fff',
                  align: 'center',
                  width: 135,
                  height: 65,
                  borderRadius: 5,
                },
              }
            },
            children: [{
              label: {
                formatter: [
                  '{first|保理额度}',
                ].join('\n'),
                rich: {
                  first: {
                    backgroundColor: '#3AC082',
                    color: '#fff',
                    align: 'center',
                    width: 135,
                    height: 65,
                    borderRadius: 5,
                  },
                }
              },
              children: [{
                label: {
                  backgroundColor: '#F4F4F4',
                  borderRadius: [0, 0, 5, 5],
                  formatter: [
                    '{first|正向保理}',
                    '{second|(CR20190912000013)\n获批金额:100\n币种:人民币}',
                  ].join('\n'),
                  rich: {
                    first: {
                      backgroundColor: '#B8D87E',
                      color: '#fff',
                      align: 'center',
                      width: 135,
                      height: 30,
                      borderRadius: [5, 5, 0, 0],
                    },
                    second: {
                      color: '#888',
                      align: 'center',
                      lineHeight: 17,
                    },
                  }
                },
              }]
            },
            {
              label: {
                formatter: [
                  '{first|租赁额度}',
                ].join('\n'),
                rich: {
                  first: {
                    backgroundColor: '#3AC082',
                    color: '#fff',
                    align: 'center',
                    width: 135,
                    height: 65,
                    borderRadius: 5,
                  },
                }
              },
              children: [
                {
                  label: {
                    backgroundColor: '#F4F4F4',
                    borderRadius: [0, 0, 5, 5],
                    formatter: [
                      '{first|车辆租赁}',
                      '{second|(CR20190912000013)\n获批金额:100\n币种:人民币}',
                    ].join('\n'),
                    rich: {
                      first: {
                        backgroundColor: '#FF6C6A',
                        color: '#fff',
                        align: 'center',
                        width: 135,
                        height: 30,
                        borderRadius: [5, 5, 0, 0],
                      },
                      second: {
                        color: '#888',
                        align: 'center',
                        lineHeight: 17,
                      },
                    }
                  },
                },
              ]
            }]
          }
        ]
      }
    }
  },
  components: {
    tree,
  }
};
</script>

看着代码不多,但是实现起来,各种查echarts的API和网上的资料,而且,由于效果图中一个节点处的文字可能会换行,文字的颜色也不同,同时有些节点处的背景色还会有两种,以及每个节点处显示的样式和文字都是不固定的,所以我们可能还要面临着将接口返回的数据再改造处理成我们想要的数据的繁琐问题,就如同传递给树节点的treeData的格式一样,相当麻烦,如果每个节点的样式都是一样的,那就好办多了,如官网的一个树状图的例子:https://www.echartsjs.com/examples/zh/editor.html?c=tree-vertical

原文地址:https://www.cnblogs.com/tnnyang/p/11663217.html

时间: 2024-10-17 02:44:47

使用echarts画一个类似组织结构图的图表的相关文章

vue+vuex+axios+echarts画一个动态更新的中国地图

一. 生成项目及安装插件 # 安装vue-cli npm install vue-cli -g # 初始化项目 vue init webpack china-map # 切到目录下 cd china-map # 安装项目依赖 npm install # 安装 vuex npm install vuex --save # 安装 axios npm install axios --save # 安装 ECharts npm install echarts --save 二. 项目结构 ├── ind

使用百度echarts画图表的步骤

1.百度echarts是一个很好用的图表工具,可以将一些数据很形象直观的展示出来,下面看一下简单的使用. 2.首先引用echarts.js 具体文档可以参考官网: http://echarts.baidu.com/tutorial.html 里面讲的很详细.而且官网也有很多的实例供我们参考. 3.引入echarts之后需要一个容器: 1)准备容器 这个容器就是将我们的数据在里面展示出来. 2)初始化echarts实例: var myCharts =  echarts.init(document.

echarts画中国地图并上色

任务是画一个中国地图,并在指定区域上颜色,学姐说用arcgis画,乖乖,4个g的安装文件,算了, 还是echarts大法好..如果想熟悉这个牛X的工具,请移步https://www.w3cschool.cn/echarts_tutorial/ 如果是写论文作图需要添加应用哦 最终效果如下: 参考了这个网址:https://www.cnblogs.com/luna666/p/9007263.html 另外还有个百度官方的例子:http://www.echartsjs.com/gallery/edi

自己画一个ActivityIndicatorView-b

苹果的UI控件中有一个UIActivityIndicatorView,俗称菊花.→_→现在我们仿照它来制作一个其它样式的指示器,如下: ActivityView.png 自定义指示器 首先画一个白色的扇形.创建一个MyLayer类继承自CALayer,重写它的绘图方法- (void)drawInContext:(CGContextRef)ctx: - (void)drawInContext:(CGContextRef)ctx {        CGContextSetRGBFillColor(c

Directx11学习笔记【十二】 画一个旋转的彩色立方体

上一次我们学习了如何画一个2D三角形,现在让我们进一步学习如何画一个旋转的彩色立方体吧. 具体流程同画三角形类似,因此不再给出完整代码了,不同的部分会再说明. 由于我们要画彩色的立方体,所以顶点结构体中加入颜色变量 struct Vertex { XMFLOAT3 pos; XMFLOAT4 color; }; 着色器代码 1 cbuffer cbPerObject 2 { 3 float4x4 gWorldViewProj; 4 }; 5 6 struct VertexIn 7 { 8 flo

ECharts学习(1)--简单图表的绘制

1.获取ECharts 官网 下载:http://echarts.baidu.com/download.html 2.在html页面中引入ECharts文件 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ECharts练习</title> <script type="text/javascript" src=&quo

ECharts(Enterprise Charts 商业产品图表库)初识

一.简介 大数据时代,重新定义图表的时候到了,所以随之ECharts就随之出现了. ECharts(Enterprise Charts 商业产品图表库) 是基于Canvas的,纯Javascript 的图表库,提供直观,生动,可交互,可个性化定制的 数据可视化图表.创新的拖拽重计算.数据视图.值域漫游等特性大大增强了用户体验,赋予了用户对数据进行挖掘.整合的能力.      ECharts 是指 Enterprise Charts(商业产品图表库),提供商业产品常用图表库,底层基于 ZRende

使用ECharts画K线图

需引入echarts.js插件,开发环境建议选择源代码版本,该版本包含了常见的警告和错误提示.下载地址 http://echarts.baidu.com/download.html 下面是代码,注释很清楚,主要是js代码,可根据项目进行增删!配置项说明: http://echarts.baidu.com/option.html#title <!DOCTYPE html> <html> <head> <meta charset="utf-8"&g

Echarts使用及动态加载图表数据

Echarts使用及动态加载图表数据 官网:http://echarts.baidu.com/ 1.文档 2.实例 名词: 1.统计维度(说明数据) 维度就是统计致力于建立一个基于多方位统计(时间.地域.访问者).全方位分析网站流量的统计标准,形成原始数据,数据视觉化,数据行为化,数据深入挖掘的数据分析的模式 2.指标(衡量数据) 指标是指可以按总数或比值衡量的具体维度元素.例如,维度"城市"可以关联指标"人口",其值为具体城市的居民总数