Echarts的树状图, 大量数据渲染时图表重叠, 全网最佳解决方案, 它来了

1,794 阅读1分钟

前言

需求: echarts树形图6级, 总共300个节点, 默认展开3级

嗯嗯, 以为很简单, 直接上数据渲染就完了, 全部展开后, 结果页面密密麻麻的重叠; 搜索全网,竟然没有很好的解决方式, 连echarts社区都没有更好的解决方案, what? 研究了一天, 必需解决它

配置参数 ? 度 ?

把 type: 'tree' 的一百多个配置参数仔仔细细看了一遍, 也尝试了, 然而并没有卵用.

那就度一下吧, 找到几篇博客都是拿到所有节点, 把每一个节点的lineHeight * 节点数去计算高度, 设置echarts总高度; 那就按照网上的方法试一下吧, 结果是默认高度6000. 我才展开3级,都没触底,高度就6000了???

认真捋一下思路

  1. 拿到所有节点;
  2. 筛选出2级以上的并且展开的节点;
  3. 计算筛选后的节点总高度, 每次展开隐藏节点时重新计算
  4. 设置echarts高度

先看对比结果

微信图片_20230809164800.png

微信图片_20230809165011.png

再上代码

<template>
  <div class="app-container">
    <div class="chart-tree">
      <div id="chart-box" ref="chart-box"></div>
    </div>
    <div class="chart-right">右侧占位</div>
  </div>
</template>
<script setup>
import * as echarts from "echarts";
const { proxy } = getCurrentInstance();

const seriesSource = ref([]);

const chartTree = ref(null);

onMounted(() => {
  chartTree.value = echarts.init(proxy.$refs["chart-box"]);
  setItemStyle(seriesSource.value);
  setChart();
});

// 处理数据样式
function setItemStyle(data = []) {
  data.forEach(item => {
    let obj = {};
    // 标签样式
    item.label = {};
    obj.lineHeight = 24;
    obj.borderRadius = 4;
    obj.borderWidth = 1;
    obj.padding = [0, 5];
    obj.position = "left";

    if (item.level == 2) {
      obj.color = "#fff";
      obj.borderColor = "#1338f4";
      obj.backgroundColor = "#1338f4";
    } else {
      obj.color = "#000";
      obj.borderColor = "#1338f4";
      obj.backgroundColor = "#fff";
    }
    item.label = obj;

    if (item.children && item.children.length) {
      setItemStyle(item.children);
    }
  });
}

function setChart() {
  let option = {
    tooltip: {
      trigger: "item",
      triggerOn: "mousemove",
      formatter: function(params) {
        let str = "";
        params.treeAncestors.forEach((item, index) => {
          if (index > 0 && index < params.treeAncestors.length - 1) {
            str += item.name + " > ";
          }
          if (index == params.treeAncestors.length - 1) {
            str += item.name;
          }
        });
        return str;
      }
    },
    series: [
      {
        type: "tree",
        data: seriesSource.value,
        top: "1%",
        left: "7%",
        bottom: "1%",
        right: "20%",
        symbolSize: 7,
        lineStyle: {
          color: "#1338f4"
        },
        roam: true,
        label: {
          formatter: function(params) {
            let tempName = "";
            if (params.data.children && params.data.children.length) {
              tempName = `${params.data.name}  (${params.data.children.length}个节点)`;
            } else {
              tempName = `${params.data.name}`;
            }
            if (params.collapsed && params.treeAncestors.length > 2) {
              return tempName;
            } else {
              return `${params.data.name}`;
            }
          }
        },
        leaves: {
          label: {
            position: "right",
            verticalAlign: "middle",
            align: "left"
          }
        },
        initialTreeDepth: 2, // 展开层级, null 表示全展开
        expandAndCollapse: true
      }
    ]
  };

  chartTree.value.setOption(option);
  maxHeight();
  chartTree.value.on("click", params => {
    maxHeight();
  });
}

function maxHeight() {
  let expandNode = 0;
  let allNodes = chartTree.value._chartsViews[0]._data.tree._nodes;
  for (let index = 0; index < allNodes.length; index++) {
    const element = allNodes[index];
    if (element.depth > 1 && element.isExpand && element.parentNode.isExpand) {
      expandNode += element.children.length;
    }
  }
  let expandNodeHeight = 30 * expandNode;
  let currentHeight = Math.max(796, expandNodeHeight);
  setTimeout(() => {
    chartTree.value.resize({ height: currentHeight });
  }, 300);
}
</script>
<style lang="scss" scoped>
.app-container {
  .chart-tree {
    flex: 1;
    overflow: hidden;
    #chart-box {
      width: 100%;
      height: 100%;
      transition: all 0.3s;
    }
  }
  .chart-right {
    width: 600px;
    overflow: hidden;
  }
}
</style>

结束语

不想细说了, 千言万语都在代码里, 虽然代码量不大,但是真真的一天没说话的搞事情