vue+echarts realizes the effect of Sanchi diagram

Foreword:

        In the case of graphics used in our project, the Sanchi diagram is considered an unpopular graphic, but it can meet our needs for a better display of the data flow between multi-level data. For example, in our actual data flow, there is a 1-to-many , in the case of many-to-many, it is inappropriate to use tree. If we use mind map, we can only display the lines, which cannot meet our needs for data visualization.

Realization effect:

Implementation code:

1. Initialization calling method

echarts mount click event: radarChart.getZr().on

echarts automatically adapts to changes in the interface: window.onresize

Source code:

let chartDom = document.getElementById("radar")
let radarChart = echarts.init(chartDom)

//配置属性值
 radarChart.setOption(option.value)

//挂载点击事件
  radarChart.getZr().on("click", event=> {
    // 第三层文字点击事件
    if (event.topTarget?.type === "tspan") {
          const text = event.topTarget.style.text
          if(text.indexOf('/') !== -1){
            console.log(event);
            console.log(text);
          }
    }
  })

//让echarts随着界面的变动自动适应
window.onresize = () => {
    radarEcharts.resize()
  }

2. Configuration properties

Note 1: echarts generally uses the grid method to add padding, which is invalid in Sanchi diagrams.

grid: {
  top: "0",
  left: "10%",
  right: "10%",
  bottom: "0",
  containLabel: true,
}

// Special method to add padding in Sanghi diagram

series: {       type: "sankey",       top: "1%", // distance on distance       bottom: "1%", // Distance to the bottom       left: "0", // Distance to the left       right: "16.5%" , // Follow the right distance




...

Note 2: The text content in the Sanchi diagram can be customized, but the layout is fixed and the generation distance will not be customized.

Note 3: The data of the Sanghi diagram uses the depth field to control which layer it is.

Source code:

option.value = {
    tooltip: {
      trigger: "item",
      triggerOn: "mousemove",
      rich: {
        "a": {
          "fontSize": 14,
          "fontWeight": 500,
          'color':'#fff',
          padding: [0, 0, 5, 0],
        }
      },
    // 鼠标滑上去的展示信息
      formatter: function(params) {
        if (params.data.source) {
          return `${params.data.source}-${params.data.target}:${params.data.value}`;
        } else {
          return `${params.name}:${params.value}`;
        }
      }
    },
    series: {
      type: "sankey",
      layout: "none",
      top: "1%",
      bottom: "1%",
      left: "0",
      right: "16.5%",
      draggable: false,
      focusNodeAdjacency: 'allEdges', // 鼠标划上时高亮的节点和连线,allEdges表示鼠标划到节点上点亮节点上的连线及连线对应的节点
      lineStyle: {
        opacity: 0.3,
        color: "gradient",
        curveness: 0.7,
      },
      label: {
        color: "#000",
        fontSize: 15,
        formatter: function (params) {
          // 一级 硕士研究生 博士研究生
          if(params.data.depth === 0 && params.data.name==='本科生') return "{a|" + params.data.name + "\n}" +"{b|" + params.data.value+ "}";
          if(params.data.depth === 0 && params.data.name==='硕士研究生') return "{a2|" + params.data.name + "\n}" +"{b2|" + params.data.value+ "}";
          if(params.data.depth === 0 && params.data.name==='博士研究生') return "{a3|" + params.data.name + "\n}" +"{b3|" + params.data.value+ "}";
          // 二级
          if(params.data.depth === 1) return "{c|" + params.data.name + "}" +"{d|" + params.data.value+ "}";
          // 三级
          if(params.data.depth === 2){
            let str = ''
            params.data.typeArr.forEach(item=>{
              // str += "{e|" + params.data.name + "/"+ item.typeName +"\n}"+"{f|" + item.value+ "\n}"
              str += "{m|" + params.data.name + "/"+ item.typeName +"}"+"{n|" + item.value+ "\n}"
            })
            return str;
          }

        },
        rich: {
          "a": {
            "fontSize": 14,
            "fontWeight": 500,
            'color':'#7BA2DF',
            padding: [0, 0, 5, 0],
          },
          "b": {
            "fontSize": 24,
            "fontWeight": 600,
            'color':'#7BA2DF',
            padding: [0, 0, 0, 0],
          },
          "a2": {
            "fontSize": 14,
            "fontWeight": 500,
            'color':'#BA86ED',
            padding: [0, 0, 5, 0],
          },
          "b2": {
            "fontSize": 24,
            "fontWeight": 600,
            'color':'#BA86ED',
            padding: [0, 0, 0, 0],
          },
          "a3": {
            "fontSize": 14,
            "fontWeight": 500,
            'color':'#59DEC6',
            padding: [0, 0, 5, 0],
          },
          "b3": {
            "fontSize": 24,
            "fontWeight": 600,
            'color':'#59DEC6',
            padding: [0, 0, 0, 0],
          },
          "c": {
            "fontSize": 16,
            "color": "#332D2D",
            "lineHeight": 20,
          },
          "d": {
            "fontSize": 16,
            "fontWeight": 600,
            "lineHeight": 20,
            "color": "#332D2D ",
            padding: [0, 0, 0, 2],
          },
          "e": {
            "fontSize": 14,
            "fontWeight": 500,
            'color':'#332D2D',
            padding: [0, 0, 5, 0],
          },
          "f": {
            "fontSize": 16,
            "fontWeight": 600,
            'color':'#332D2D',
            padding: [0, 0, 20, 0],
          },
          "m": {
            "fontSize": 14,
            "fontWeight": 500,
            'color':'#332D2D',
            padding: [0, 0, 0, 0],
          },
          "n": {
            "fontSize": 16,
            "fontWeight": 600,
            'color':'#332D2D',
            padding: [0, 0, 0, 10],
          },
        },
      },
      // nodeWidth:100,
      nodeGap: 20, // 每一组之间的距离
      layoutIterations: 0,// 自动优化列表,尽量减少线的交叉,为0就是按照数据排列
      emphasis: {
        focus: "adjacency",
      },
      data: allData,
      links: allGuideData,
    },
  }

3. Fill in test data:

// 测试数据1
  let allData= [
    { name: "本科生",value:430, itemStyle: { color: "#7BA2DF" }, depth: 0 },
    { name: "硕士研究生",value:60, itemStyle: { color: "#BA86ED" }, depth: 0 },
    { name: "博士研究生",value:60, itemStyle: { color: '#59DEC6' }, depth: 0 },
    { name: "预防医学",value:60, itemStyle: { color: '#5FD981' }, depth: 1 },
    { name: "综合楼",value:60, itemStyle: { color: "#00baff" }, depth: 1 },
    { name: "2022级",typeArr:[{typeName:"本科",value:50},{typeName:"硕士研究生",value:30}], itemStyle: { color: "#f8b551" }, depth: 2 },
    { name: "2021级",typeArr:[{typeName:"硕士研究生",value:50}], itemStyle: { color: "#7ecef4" }, depth: 2 },
    { name: "2023级",typeArr:[{typeName:"博士研究生",value:50}], itemStyle: { color: "#7ecef4" }, depth: 2 },
  ]

  // 测试数据2,连线
  let allGuideData = [
    // L1→L3	 4509
    { source: "本科生", target: "预防医学", value: 800 },
    // L2→L3	 12196
    { source: "硕士研究生", target: "预防医学", value: 200 },
    // L1→L2→L3	 2404
    { source: "综合楼", target: "2022级", value: 200 },
    { source: "综合楼", target: "2023级", value: 200 },
    { source: "博士研究生", target: "2022级", value: 300 },
    { source: "预防医学", target: "2021级", value: 400 },
    { source: "预防医学", target: "2023级", value: 100 },
  ]

4. More, official API:

Official api about Sankeytu apiicon-default.png?t=N7T8https://echarts.apache.org/zh/option.html#series-sankey.type

More Sanchi chart informationicon-default.png?t=N7T8https://www.ppchart.com/#/

Guess you like

Origin blog.csdn.net/weixin_44727080/article/details/134823323