目录

第15节复杂数据图表树形图

本资源由 itjc8.com 收集整理

第 15 节 复杂数据图表 · 树形图

翻过了关系图谱这座小山丘之后,让我们继续回忆一下我们在前面就提到过的一种特殊的关系图谱——树形。树形结构有着非常明确的上下级关系,可以非常直观地表达出事物的因果关系,且其规则复杂却足够灵活,因而能够很好地使用在各种算法和场景中。

使用 ECharts 来对树形结构进行可视化,可以为这种强大的数据结构加上更强的交互性,能让你的用户更好地梳理和理解树形结构中所承载的内容。

15.1 准备数据

在第 7 节中我们介绍了如何利用树形结构及其相关的运算算法来对一系列关系数据进行处理,而本章节我们将要使用 ECharts 进行具有可交互特性的图表可视化。

和在上一节中的关系图谱中所使用的数据集类似,由于 ECharts 对数据集进行应用之前都需要先进行一系列的预处理,而这过程中很有可能会与我们所实现的类中的某些属性或方法相冲突。

所以我们需要准备一个转换函数,将我们第 7 节中所生成的树形结构数据转换为更纯粹的 JavaScript 对象数据,也就是俗称的 JSON 数据。

const root = new Node('root')
const node1 = new Node('node 1')
const node2 = new Node('node 2')
const node3 = new Node('node 3')
const node4 = new Node('node 4')
const node5 = new Node('node 5')
const node6 = new Node('node 6')

const tree = new Tree(root)
tree.addNode(node1)
tree.addNode(node2)
tree.addNode(node3, node1)
tree.addNode(node4, node1)
tree.addNode(node5, node2)
tree.addNode(node6, node5)

function treeDataHelper(treeNode) {
  const node = {
    value: treeNode.value
  }

  if (treeNode.children && treeNode.children.length > 0) {
    node.children = node.children || []

    treeNode.children.forEach(function(childNode) {
      node.children.push(treeDataHelper(childNode))
    })
  }

  return node
}

const pureRoot = treeDataHelper(tree.root)

15.2 编写配置

ECharts 在这种较为复杂的数据图表中有着非常优秀的封装,它可以帮助我们很快地将复杂的数据结构根据图表配置展示出我们所希望看到的可视化图表,这一特点在树形图中尤为明显。

const option = {
  series: {
    type: 'tree',
    data: [ pureRoot ]
  }
}

https://user-gold-cdn.xitu.io/2018/9/22/16600db1765073ff?w=600&h=400&f=png&s=12604

Live DEMO: https://codepen.io/iwillwen/pen/zJXBEV

Bravo!极其简单的配置便可以得到样式良好且可交互的树形图表,但我们发现在树形图中节点并没有将节点的名称展示出来,那么接下来我们依然是进入我们非常熟悉的图表优化环节。

图表优化

显示节点名称

事实上 ECharts 的树形图在不需要添加任何配置项的情况下也可以展示节点的名称,不过因为我们在第 7 节中所指定的节点类 Node 中代表节点值或名称的属性为 value 而 ECharts 树形图中则需要使用 name,所以便无法直接展示出节点的名称。

而这一问题也并不是无法解决的,我们可以使用 label.formatter 的方式为节点添加标签。

const option = {
  series: {
    // ...
    
    label: {
      formatter: '{@value}' // 绑定到 value 属性上
    }
  }
}

https://user-gold-cdn.xitu.io/2018/9/22/16600db17685bc08?w=600&h=400&f=png&s=15647

Live DEMO: https://codepen.io/iwillwen/pen/aaxZEo

但是我们还发现这个配置虽然满足了在图表上显示节点名称的需求,却出现了名称与节点图标重叠的情况。那么我们便需要对这个情况进行调整,以帮助图表的使用者和阅读者更好地使用。

调整节点名称位置

在对数据进行调整之前,我们需要明确调整的思路。因为树形结构中的节点除了根节点都会与上一层的父节点有一条连线以表示节点之间的父子关系,但相对的每一个节点与上一层父节点的关系数量只有一个,但却有可能有很多的子节点与自身有关系,所以如果将节点的名字放在了节点的右方便很有可能会出现严重的与节点的边相重叠。

所以对于叶节点以外的所有节点,我们需要将名字显示在节点的左边,而因为叶节点是没有子节点的,所以叶节点的名称可以显示在节点图标的右边。

const option = {
  series: {
    // ...
    
    label: {
      position: 'left'
    },
    
    leaves: {
      label: {
        position: 'right'
      }
    }
  }
}

https://user-gold-cdn.xitu.io/2018/9/22/16600db176625b85?w=600&h=400&f=png&s=16749

Live DEMO: https://codepen.io/iwillwen/pen/qMwNxd

15.3 其他树形图形态

就如上一节中关系图谱的两种模板,除了默认的从左往右伸展的树形图结构以外,ECharts 的树形图表也提供了多种不同的结构模板。

除了最基本的从左往右展开排列以外,还有其他三个方向的模板(如从上往下)。除此以外还有一个十分好看的放射形树形图。

const option = {
  series: {
    type: 'tree',
    layout: 'radial',
    data: [ treeDataHelper(tree.root) ],
    label: {
      formatter: '{@value}'
    }
  }
}

https://user-gold-cdn.xitu.io/2018/9/22/16600db1767d9abb?w=600&h=400&f=png&s=16740

Live DEMO: https://codepen.io/iwillwen/pen/LJvZdG

这里的效果稍微有点差,当然这是因为节点的数量太少了。

小结

这一节中我们学习了另外一种复杂数据结构——树形结构的可视化图表的使用,其中因为 ECharts 对数据的内部处理导致了我们需要利用其他手段将我们原本实现的树形结构转换为更纯净的 JavaScript 对象数据集,那么我们本节的习题也会从这一个点上进行练习。

习题

在上一节中我们并没有为关系图谱数据设计类似 treeDataHelper 这样的函数,而在本节中我们利用了递归的方式进行了逐层的转换来对树形结构进行了转换。

请模仿 treeDataHelper 编写出适用于上一节中关系图谱数据的 graphDataHelper