用echarts实现美丽的力导向图

5,171 阅读3分钟

1.什么是力引导布局

  • 力引导布局是模拟弹簧电荷模型在每两个节点之间添加一个斥力,每条边的两个节点之间添加一个引力,每次迭代节点会在各个斥力和引力的作用下移动位置,多次迭代后节点会静止在一个受力平衡的位置,达到整个模型的能量最小化。

2.结合实现结果理解力引导布局

  • 红色箭头对立为斥力,相反为引力,页面中的所有节点都是一个有能量的粒子,这种相互作用力最终会趋于平衡,形成这种对称的效果

3.echarts配置

    let option = {
      tooltip: {
        show: true,
        formatter: "<div style='display:block;word-break: break-all;word-wrap: break-word;white-space:pre-wrap;max-width: 80px'>" + "{b} " + "</div>"
      },
      series: [{
        type: 'graph', // 声明绘制关系图
        layout: 'force', // 声明绘制关系图中的力导向图 
        symbolSize: 40, 
        draggable: true, // 节点是否可拖拽
        roam: true,  // 是否开启鼠标缩放和平移漫游
        focusNodeAdjacency: true, // 是否在鼠标移到节点上的时候突出显示节点以及节点的边和邻接节点
        edgeSymbol: ['', 'arrow'],
        cursor: 'pointer',
        emphasis: { //  鼠标悬浮高亮图形的样式
          itemStyle: {
            borderColor: 'black',
            borderWidth: 1,
            borderType: 'solid',
            symbolSize: 40,
          },
          label: {
            show: true,
            formatter: (record) => {
              if (record.name.length > 10) {
                return record.name.substr(0, 5) + '...'
              } else {
                return record.name
              }
            }
          }
        },
        edgeLabel: { // 设置连线label样式
          normal: {
            show: true,
            textStyle: {
              fontSize: 12,
              color: '#fff'
            },
            formatter(x) {
              return x.data.name;
            }
          }
        },
        label: { // 节点label设置
          show: true,
          position: 'bottom',
          color: '#fff',
          formatter: (record) => {
            console.log(record)
            return '节点' + record.dataIndex
            // if (record.name.length > 10) {
            //   return record.name.substr(0, 5) + '...'
            // } else {
            //   return record.name
            // }
          }
        },
        force: { // 力引导布局相关的配置项
          repulsion: 80, // 节点之间的斥力因子
          gravity: 0.02, // 节点受到的向中心的引力因子 越大越往中心靠拢
          edgeLength: 240, // 边的两个节点之间的距离
          layoutAnimation: true, // 显示布局的迭代动画
        },
        nodes: nodes,  // 节点数据列表
        links: links, // 关系数据列表
      }]
    }

4.在react项目中使用 echarts-for-react

  • echarts-for-react 是基于echarts封装的react可视化插件
  • npm install --save echarts-for-react (安装npm包)
  • import ReactEcharts from 'echarts-for-react'; (页面引入)
import ReactEcharts from 'echarts-for-react';

class GraphDemo extends React.Component {
   constructor(props) {
      super(props)
      this.ChartRef = React.createRef();
      this.state = {
        graphData: {
          nodes: [],
          links: [],
        },
      }
   }
  onclick = {
    'click': this.clickEchartsPie.bind(this),
    'dblclick': this.dblclickPie.bind(this),
    'contextmenu': this.rightMouse.bind(this),
    // 'mouseover': this.mouseoverNode.bind(this)
  }
  clickEchartsPie (e) {
    
  }
  
  getOption () {
    let option = {
       ...//
    }
    return option
  }
  render () {
    return <div>
          <ReactEchart 
            ref={this.ChartRef} 
            onEvents={this.onclick} 
            style={{ height: '600px' }} 
            option={this.getOption(graphData)} 
          />
      </div>
  }
}

5.事件绑定

  • 要在图谱上完成一些复杂业务逻辑,就需要用到很多事件,如 单击,双击,右键,鼠标悬浮等
  • echarts提供了很多鼠标事件,如图
  • echarts-for-react也提供了事件绑定的方法,如图:

6.图谱的放大缩小,清空

  • 获取图谱的实例,就可以进行动态设置option,通过zoom属性设置图谱缩放
  // 放大
  add() {
    let echartInstance = this.ChartRef.current.getEchartsInstance();
    let zoom = echartInstance.getOption().series[0].zoom;
    const addNum = 0.2;
    zoom += addNum
    echartInstance.setOption({
      series: {
        zoom
      }
    })

  }
  // 缩小
  decrese() {
    let echartInstance = this.ChartRef.current.getEchartsInstance();
    let zoom = echartInstance.getOption().series[0].zoom;
    const addNum = 0.2;
    zoom -= addNum
    echartInstance.setOption({
      series: {
        zoom
      }
    })
  }
  // 清空
  clear () {
    let echartInstance = this.ChartRef.current.getEchartsInstance();
    echartInstance.clear() // 清除当前实例
    echartInstance.dispose() // 销毁实例
  }

7.结语

  • 了解了如何实现力导向图,也了解了如何绑定事件,nam就可以在此基础上进行更加复杂的业务操作。

本文使用 mdnice 排版