Echarts tree结构使用

需求:关系族谱图,多叉树结构展示

技术:Echarts tree结构

难点

  1. 控制节点的缩起和展开状态
  2. 同一个等级的只能展开一个节点
  3. 控制高度的自动伸缩

知识

  1. 数组的递归
  2. ES6 map的使用

tree结构的数据结构以及配置项

option: {
    series: [
      {
        type: 'tree',  // 类型是tree
        top: '1%',  //距离div块top距离
        left: '10%',
        bottom: '1%',
        right: '10%',
        // 每个节点都有文字,label属性是设置字体(位置,大小,样式)
        label: {
          normal: {
            position: 'left',
            verticalAlign: 'middle',
            align: 'right',
            fontSize: 12
          }
        },
        // 当此节点下还有子节点时候,设置的节点样式,用于区别 没有子节点的节点的样式
        itemStyle: {
          normal: {
            color: '#b22125'
          },
          emphasis: {
            borderColor: '#ccc'
          }
        },
        // 叶子节点设置
        leaves: {
          label: {
             normal: {
               position: 'right',
               verticalAlign: 'middle',
               align: 'left',
               fontSize: 12
             }
           }
        },
        // 图形大小
        symbolSize: 20,
        initialTreeDepth: 2,   // 一开始展开深度
        // expandAndCollapse  全部打开,全部收缩,值未布尔类型
        data: []
      }
    ]
  }

一切准备就绪,开始上代码

  1. 初始化echarts
<div id="tree">
  <div id="myChart"></div>
</div>
this.myChart = echarts.init(document.getElementById('myChart'))
this.myChart.on('contextmenu', this.handleClick)  // 右击,弹窗弹出此节点的详情;有一个参数param(可以打印出来)
this.myChart.on('click', this.handleClickCircle)  // 左击,控制节点的展开和伸缩;有一个参数param(可以打印出来)
  1. 右击,弹窗弹出此节点的详情,在此处,右击浏览会弹出菜单,需要屏蔽掉默认事件
// 自带param参数
handleClick(param) {
  let _this = this
  param.event.event.preventDefault()  //屏蔽浏览器默认行为
  this.Ajax.post(url, data, this,
    function(data, context) {
      Object.keys(data.data).forEach(key => {
       // 对数据进行一些处理
      })
    }
  )
}
  1. 左击,控制节点的伸缩和展开,高度计算
//右击的时候,需要判断此节点是否已经展开
//节点的展开和收缩状态存储在一个map中,map中的key是此节点的唯一标示(唯一标识自己和后台定啦),value为true或者false(true为收缩状态,false为展开状态);每次点击取到这个节点的唯一标识,然后从map中取出此节点是展开还是缩起的状态
//如果已经展开,就执行默认的行为(收缩起来);并且将map中此节点的唯一标示改为true
//如果点击节点并且此节点是缩起的状态,这个时候需要将同级的节点全部收起来,只设置此节点是展开状态;并且将map中此节点的唯一标示改为false
handleClickCircle(param) {
    let index = param.data.index  // 获取当钱节点的深度param.data是自己传的数据
    this.findId(this.option.series[0].data, param.value, 'getObj')   // 获取当前节点
    // 判断此节点是展开还是收缩状态
    if (this.map.get(this.currentClickObj.value)) {
        // 收缩状态,执行下面代码
        this.map.set(this.currentClickObj.value, false)
        // 将同级的全部收缩   this.option.series[0].data是本树的data数据(数组)
        this.handleCollapsed(this.option.series[0].data, index)
        // 当前节点展开
        this.findId(this.option.series[0].data, param.value, 'setCollapsed')
        this.map.set(this.currentClickObj.value, true)  // 将当前节点设置为收缩状态
        // 重新渲染  echart中的data更改的时候,需要重新渲染
        this.myChart.clear()
        this.myChart.setOption(this.option)
    }
    // 计算高度
    //计算高度这个点,我是查找此子树的每个级别的节点,并找出最多的节点数,根据这个子节点数来计算高度
    this.listNumber = []
    let charts = document.getElementById('myChart')
    this.findMostLeaves(param.data.index + 1)
    // Math.max.apply(null, this.listNumber) 取出listNumber中的最大值并且计算高度
    charts.style.height = Math.max.apply(null, this.listNumber) * 80 + 500 + 'px'
    // 重要的一步,小编当时就是漏掉此步,导致没办法更新高度,敲黑板
     this.myChart.resize()
  },
//////////////////////////分割线//////////////////////////
// 将同级的全部收缩
handleCollapsed(array, index) {
  array.forEach((value, i) => {
    if (value.index == index) {
      value.collapsed = true  // collapsed属性为true,设置此节点收缩状态
      this.map.set(value.value, false)  // 并且将此节点设置为可收缩状态(map)
    } else {
      if (value.children.length > 0) {
        // 递归
        this.handleCollapsed(value.children, index)
      } else {
        return
      }
    }
  })
}
//////////////////////////分割线//////////////////////////
// 查找当前节点  当前节点展开
findId(array, id, flag) {
  array.forEach((value, i) => {
    if (value.value == id) {
      if (flag == 'setCollapsed') {
        value.collapsed = false  //collapsed属性为true,设置此节点展开状态
        this.map.set(value.value, true)  // 并且将此节点设置为可展开状态(map)
      } else {
        this.currentClickObj = value
      }
    } else {
      if (value.children.length > 0) {
        this.findId(value.children, id, flag)
      } else {
        return
      }
    }
  })
}
//////////////////////////分割线//////////////////////////
// 找出最多的节点
findMostLeaves(index) {
  // this.myChart._chartsViews[0]._data.tree._nodes 此值是tree数据将结构中的数据,左击的时候就可以获取到此数值,并且里面的isExpand就是判断当前节点的展开和收缩状态
  this.myChart._chartsViews[0]._data.tree._nodes.forEach(value => {
    if (value.depth <= index) {
      if (value.isExpand) {
        // 将每一个等级的叶子数量存入listNumber中
        this.listNumber.push(value.children.length)
      }
    }
  })
}
  1. 我当时这篇文章帮了我很多,可以参考
  2. 此过程中用到的map类型,将在下期总结ES6的map和set的用法(敬请期待鸭)

感谢您的view,留个赞再走呗

  • 感谢浏览姑娘的文章,来自一个写前端的姑娘!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。