金字塔

描述:当前是关于Echarts图表中的 示例。
 
              // 原始数据
  let data = [
    { name: "测试数据", value: 4 },
    { name: "测试原理", value: 2 },
    { name: "测试功能", value: 8 },
    { name: "测试功能1", value: 10 },
    { name: "测试功能2", value: 6 },
  ];
  // 将数据根据从小到大排序
  let newdata = sortObject(data);
  // 图例数据
  let lengthData = [];
  // 返回数据
  let resultData = data.map((item, index) => {
    let graw = 100;
    lengthData.push({
      type: "group",
      top: index * 25,
      scale: [1, 1],
      children: [
        {
          type: "circle",
          shape: {
            cx: 0,
            cy: 7,
            r: 5,
          },
          style: {
            fill: index === 0 ? "#07a9ab" : index === 1 ? "#008CD2" : "#0847e7",
          },
        },
        {
          type: "text",
          style: {
            text: item.name,
            fill: "#ccc",
            fontSize: 14,
            x: 10,
            y: 2,
          },
        },
        {
          type: "text",
          name: item.name,
          style: {
            text: item.value,
            fill: "#ccc",
            fontSize: 17,
            x: 80,
            y: 0,
          },
        },
        {
          type: "text",
          style: {
            text: "个",
            fill: "#ccc",
            fontSize: 14,
            x: graw,
            y: 2,
          },
        },
      ],
    });
    if (index === 0) {
      return {
        style: {
          fill: "#37CCCA",
        },
        ...item,
      };
    } else if (index === 1) {
      return {
        style: {
          fill: "#34A6BF",
        },
        ...item,
      };
    } else if (index === 2) {
      return {
        style: {
          fill: "#307AB3",
        },
        ...item,
      };
    } else if (index === 3) {
      return {
        style: {
          fill: "#2E54A9",
        },
        ...item,
      };
    } else if (index === 4) {
      return {
        style: {
          fill: "#2E43A9",
        },
        ...item,
      };
    }
  });
  // 获取计算的数据
  let getData = pyramidChart(resultData, document.getElementById("container"));
  option = {
     backgroundColor:"#000",
    tooltip: {},
    graphic: [
      {
        type: "group",
        left: "5%",
        top: "center",
        scale: [1, 1],
        onclick: function (params) {},
        children: getData,
      },
      {
        type: "group",
        left: "50%",
        top: "center",
        scale: [1, 1],
        onclick: function (params) {},
        children: lengthData,
      },
    ],
    series: [],
  };
  // 排序
  function sortObject(arr) {
    return arr.sort(function (a, b) {
      return a["value"] - b["value"];
    });
  }
  // 数据处理
  function pyramidChart(data = [], dom, option = {}) {
    let domHeight = dom ? dom.clientHeight - 40 : 0;
    let domWidth = dom ? dom.clientWidth - 40 : 0;
    // 默认获取一个正方形空间
    let maxDistance = domHeight > domWidth / 2 ? domWidth / 2 : domHeight;
    // 合并设置
    let resultOption = Object.assign(
      {
        slanted: 1, // 每层底部的倾斜度
        maxWidth: maxDistance, // 金字塔最大宽度
        maxHeight: maxDistance, // 金字塔最大高度
        offset: 35, //偏差
      },
      option
    );
    if (data.length === 1) {
      resultOption.slanted = 40;
    }
    if (data.length === 2) {
      resultOption.slanted = 25;
    }
    if (data.length === 3) {
      resultOption.slanted = 15;
    }
    if (data.length === 4) {
      resultOption.slanted = 10;
    }
    if (data.length === 5) {
      resultOption.slanted = 6;
    }
    // 减去多余的误差边距
    resultOption.maxHeight = resultOption.maxHeight - resultOption.offset;
    // 一半最大宽度,用于计算左右边距
    let halfMaxWidth = resultOption.maxWidth / 2;
    // 数据最终
    let resultData = [];
    // 数据值 数组
    let dataNums = data.map((item) => item.value || 0);
    // 计算数据总和
    let dataNumSum =
      dataNums.length > 0 &&
      dataNums.reduce(function (prev, curr) {
        return Number(prev || 0) + Number(curr || 0);
      });
    // 中间数据点坐标数组 根据长度比值算出
    let midlinePoint = [];
    let multipleLayer = [0.6];
    // 计算倍数等基础数据
    dataNums.forEach((item, index, arr) => {
      let itemNext = arr[index + 1];
      if (itemNext) {
        multipleLayer.push(itemNext / dataNums[0]); // 计算倍数
      }
      // 计算点坐标 长度
      let point =
        Math.round((item / dataNumSum) * resultOption.maxHeight * 1000) / 1000;
      midlinePoint.push(point);
    });
    // 三角形的高度
    let triangleHeight = 0;
    let triangleHeightLayer = [];
    // 三角形tan角度
    let triangleRatio = halfMaxWidth / resultOption.maxHeight;
    midlinePoint.forEach((item) => {
      triangleHeight = triangleHeight + item;
      triangleHeightLayer.push(triangleHeight);
    });
    // 中间数据点 最后的数据长度
    let midlinePointFinally =
      triangleHeightLayer[triangleHeightLayer.length - 1] || 0;
    // 开始拼接数据
    data.forEach((item, index) => {
      let arrObj = [];
      let triangleHeightLayerOne = triangleHeightLayer[index];
      let triangleHeightLayerOneLast = triangleHeightLayer[index - 1] || 0;
      let multipleLayerOne = multipleLayer[index];
      let multipleLayerOneLast = multipleLayer[index - 1] || 0;
      // 第一层数据单独处理
      if (index === 0) {
        arrObj.push(
          [0, 0],
          [
            -triangleRatio *
              (triangleHeightLayerOne -
                resultOption.slanted * multipleLayerOne),
            triangleHeightLayerOne - resultOption.slanted * multipleLayerOne,
          ],
          [0, triangleHeightLayerOne],
          [
            triangleRatio *
              (triangleHeightLayerOne -
                resultOption.slanted * multipleLayerOne),
            triangleHeightLayerOne - resultOption.slanted * multipleLayerOne,
          ]
        );
      } else {
        arrObj.push(
          [0, triangleHeightLayerOneLast],
          [
            -triangleRatio *
              (triangleHeightLayerOneLast -
                resultOption.slanted * multipleLayerOneLast),
            triangleHeightLayerOneLast -
              resultOption.slanted * multipleLayerOneLast,
          ],
          [
            -triangleRatio *
              (triangleHeightLayerOne -
                resultOption.slanted * multipleLayerOne),
            triangleHeightLayerOne - resultOption.slanted * multipleLayerOne,
          ],
          [0, triangleHeightLayerOne],
          [
            triangleRatio *
              (triangleHeightLayerOne -
                resultOption.slanted * multipleLayerOne),
            triangleHeightLayerOne - resultOption.slanted * multipleLayerOne,
          ],
          [
            triangleRatio *
              (triangleHeightLayerOneLast -
                resultOption.slanted * multipleLayerOneLast),
            triangleHeightLayerOneLast -
              resultOption.slanted * multipleLayerOneLast,
          ]
        );
      }
      resultData.push({
        type: "polygon",
        z: 1,
        shape: {
          points: arrObj,
        },
        name: item.name,
        style: item.style,
      });
    });
    // 添加线
    resultData.push({
      type: "polyline",
      shape: {
        points: [
          [0, 0],
          [0, midlinePointFinally],
        ],
      },
      style: {
        stroke: "#f2f2f2",
        opacity: 0.2,
        lineWidth: 1,
      },
      z: 2,
    });

    // 返回
    return resultData;
  }