D3 v4.x学习(1-8)—— 集群图探究(普通和环形)

集群图本身和树状图差不多,因此也是用于处理树形结构数据的,和树状图不同的是,集群图的所有叶子节点(每个分支深度最深的节点)都放在统一深度的位置上,因此可以利用这个特性做一个圆,后面会给出源码。

<template>
  <div id='svgContainer' style="">
    <div class="every">
      <h3>集群图探究</h3>
      <div class="svg" id="clusterDiagram"></div>
    </div>
  </div>
</template>
<script>
import * as d3 from 'd3'
export default {
 data () {
    return {
        treeData: {
        'name': '中国',
        'children': [
          {
            'name': '浙江',
            'children':
            [
              {'name': '杭州'},
              {'name': '宁波'},
              {'name': '温州'},
              {'name': '绍兴'}
            ]
          },
          {
            'name': '广西',
            'children': [
              {
                'name': '桂林',
                'children':
                [
                  {'name': '秀峰区'},
                  {'name': '叠彩区'},
                  {'name': '象山区'},
                  {'name': '七星区'}
                ]
              },
              {'name': '南宁'},
              {'name': '柳州'},
              {'name': '防城港'}
            ]
          },
          {
            'name': '黑龙江',
            'children': [
              {'name': '哈尔滨'},
              {'name': '齐齐哈尔'},
              {'name': '牡丹江'},
              {'name': '大庆'}
            ]
          },
          {
            'name': '新疆',
            'children':
              [
                {'name': '乌鲁木齐'},
                {'name': '克拉玛依'},
                {'name': '吐鲁番'},
                {'name': '哈密'}
              ]
          }
        ]
      }
    },
    methods: {
        clusterDiagram () {
      // 树状图因为默认是上往下渲染的,改成从左往右渲染后会发现width和height都倒过来了,可以看具体参数的细节
      let width = 400
      let height = 400
      let _this = this
      let svg = d3.select('#clusterDiagram')
        .append('svg')
        .attr('width', width)
        .attr('height', height)
      // 初始化树状图数据获取器
      let cluster = d3.cluster()
        .size([width, height - 80])
        .separation(function (a, b) {
          return (a.parent === b.parent ? 1 : 2) / a.depth
        })
      // 初始化json数据转成一棵树,这个步骤是非常必要的!!
      let hierarchyData = d3.hierarchy(_this.treeData)
        .sum(function (d) {
          return d.value
        })
      // 初始化树状图
      let treeData = cluster(hierarchyData)
      // 获取节点
      let nodes = treeData.descendants()
      // 获取边,也就是连线
      let links = treeData.links()
      // 绘制线
      let g = svg.append('g').attr('transform', 'translate(40,0)')
      g.selectAll('.link')
        .data(links)
        .enter().append('path')
        .attr('class', 'link')
        .style('fill', '#cccccc')
        .attr('d', d3.linkHorizontal()
          .x(function (d) { return d.y })
          .y(function (d) { return d.x }))
      // 绘制文本和节点
      g.selectAll('.node')
        .data(nodes)
        .enter().append('g')
        .attr('class', function (d) { return 'node' + (d.children ? ' node--internal' : ' node--leaf') })
        .attr('transform', function (d) { return 'translate(' + d.y + ',' + d.x + ')' })
      g.selectAll('.node').append('circle')
        .attr('r', 5)
        .style('fill', 'green')
      g.selectAll('.node').append('text')
        .attr('dy', 3)
        .attr('x', function (d) { return d.children ? -8 : 8 })
        .style('text-anchor', function (d) { return d.children ? 'end' : 'start' })
        .text(function (d) {
          return d.data.name
        })
        .style('font-size', '11px')
    },
    },
    mounted () {
        this.clusterDiagram()
    }
}
</script>
<style lang="less">
#svgContainer{
  width: 100%;
  height: 100%;
  .every{
    width: 400px;
    height: 425px;
    margin:15px;
    float: left;
    h3{
      margin:0;
      .button{
        float: right;
        margin-right: 20px;
        font-size: 14px;
        cursor: pointer;
        padding: 2px 8px;
        border:1px solid #ccc;
        background: yellowgreen;
        border-radius: 4px;
        &:hover{
          background: violet;
        }
      }
    }
    .svg{
      width: 400px;
      height: 400px;
    }
  }
}
</style>

利用集群图的特性做一个环形的树状图,如下图

<template>
  <div id='svgContainer' style="">
    <div class="every">
      <h3>利用集群图的特性做个圆</h3>
      <div class="svg" id="clusterCircle"></div>
    </div>
  </div>
</template>
<script>
import * as d3 from 'd3'
export default {
 data () {
    return {
        treeData: {
        'name': '中国',
        'children': [
          {
            'name': '浙江',
            'children':
            [
              {'name': '杭州'},
              {'name': '宁波'},
              {'name': '温州'},
              {'name': '绍兴'}
            ]
          },
          {
            'name': '广西',
            'children': [
              {
                'name': '桂林',
                'children':
                [
                  {'name': '秀峰区'},
                  {'name': '叠彩区'},
                  {'name': '象山区'},
                  {'name': '七星区'}
                ]
              },
              {'name': '南宁'},
              {'name': '柳州'},
              {'name': '防城港'}
            ]
          },
          {
            'name': '黑龙江',
            'children': [
              {'name': '哈尔滨'},
              {'name': '齐齐哈尔'},
              {'name': '牡丹江'},
              {'name': '大庆'}
            ]
          },
          {
            'name': '新疆',
            'children':
              [
                {'name': '乌鲁木齐'},
                {'name': '克拉玛依'},
                {'name': '吐鲁番'},
                {'name': '哈密'}
              ]
          }
        ]
      }
    },
    methods: {
           clusterCircle () {
      let width = 400
      let height = 400
      let _this = this
      let svg = d3.select('#clusterCircle')
        .append('svg')
        .attr('width', width)
        .attr('height', height)
      // 初始化树状图数据获取器
      let cluster = d3.cluster()
        .size([width, height - 80])
        .separation(function (a, b) {
          return (a.parent === b.parent ? 1 : 2) / a.depth
        })
      // 初始化json数据转成一棵树,这个步骤是非常必要的!!
      let hierarchyData = d3.hierarchy(_this.treeData)
        .sum(function (d) {
          return d.value
        })
      // 初始化树状图
      let treeData = cluster(hierarchyData)
      // 获取节点
      let nodes = treeData.descendants()
      // 获取边,也就是连线
      let links = treeData.links()
      // 绘制线
      let g = svg.append('g').attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')')
      g.selectAll('.link')
        .data(links)
        .enter().append('path')
        .attr('class', 'link')
        .style('fill', '#cccccc')
        // 根据官网API 返回 d.x 和 d.y绘制出来的线就是一坨shit,猜了一个小时终于猜出来了
        .attr('d', d3.linkRadial()
          .angle(function (d) { return d.x / 180 * Math.PI })
          .radius(function (d) { return d.y / 2 }))
      // 绘制文本和节点
      g.selectAll('.node')
        .data(nodes)
        .enter().append('g')
        .attr('class', function (d) { return 'node' + (d.children ? ' node--internal' : ' node--leaf') })
        .attr('transform', function (d) { return 'rotate(' + (d.x - 90) + ')translate(' + d.y / 2 + ')' })
      g.selectAll('.node').append('circle')
        .attr('r', 5)
        .style('fill', 'green')
      g.selectAll('.node').append('text')
        .attr('dx', function (d) { return d.x < 180 ? 8 : -8 })
        .attr('dy', '.31em')
        .attr('text-anchor', function (d) { return d.x < 180 ? 'start' : 'end' })
        .attr('transform', function (d) { return d.x < 180 ? null : 'rotate(180)' })
        .text(function (d) { return d.data.name })
        .style('font-size', '11px')
    }
    },
    mounted () {
        this.clusterCircle()
    }
}
</script>
<style lang="less">
#svgContainer{
  width: 100%;
  height: 100%;
  .every{
    width: 400px;
    height: 425px;
    margin:15px;
    float: left;
    h3{
      margin:0;
      .button{
        float: right;
        margin-right: 20px;
        font-size: 14px;
        cursor: pointer;
        padding: 2px 8px;
        border:1px solid #ccc;
        background: yellowgreen;
        border-radius: 4px;
        &:hover{
          background: violet;
        }
      }
    }
    .svg{
      width: 400px;
      height: 400px;
    }
  }
}
</style>

猜你喜欢

转载自blog.csdn.net/dkr380205984/article/details/81667546