stackChart.vue 7.77 KB
<template>
  <div>
     <basic ref="basic" :chartId="chartId" :chartData="chartData"></basic>
  </div>
</template>
<script>
import mixin from './mixin';
export default {
  mixins: [mixin],
  data() {
    return {

    }
  },
  methods: {
    /**
     * 预处理option参数
     * */
    preChartData(cdata) {
       return cdata;
    },
    /**
     * 处理option参数
     * */
    dealChartData(optionFormat) {
      // 特殊配置项
      let { _color, yAxisName, doubleYaxis, isSwapY, grid,legendShow=true,perUnit = this.$t("format.perTime") } = optionFormat.otherConf;
      optionFormat.xAxis.boundaryGap = true;
      // perTime perNum
      optionFormat.yAxis.name = yAxisName || perUnit;
      optionFormat.yAxis.nameRotate = 1;
      optionFormat.legend.itemGap = 32;
      optionFormat.legend.bottom = 12;
      optionFormat.legend.show = legendShow;
      optionFormat.tooltip.trigger = "axis";
      optionFormat.tooltip.axisPointer = {
        type: "line",
        // animation: true,
        lineStyle: {
          color: "transparent"
        }
      };

      let seriesObj = {},
        seriesData = [],
        totalData = [],
        totalNum = 0,
        ageArr = [];
      seriesData = optionFormat.xAxis.data.map(item => {
        return {
          name: item,
          data: []
        };
      });
      
      let ageNum;
      optionFormat.series.forEach((item, index) => {
        ageNum = 0;
        item.data.forEach((dataItem, dataIndex) => {
          seriesObj[optionFormat.xAxis.data[dataIndex]] = item.data[dataIndex];
          totalNum += item.data[dataIndex];
          ageNum += item.data[dataIndex];
          for (let k in seriesObj) {
            if (seriesData[dataIndex] && seriesData[dataIndex].name === k) {
              seriesData[dataIndex].data.push(seriesObj[k]);
            }
          }
          seriesObj = {};
        });
        ageArr.push(ageNum);
      });
      const that = this;
      let legendTempData = Object.assign([], optionFormat.legend.data).map(
        item => item.name
      );
      optionFormat.legend.data = [];
      seriesData.forEach((item,idx) => {
        item.itemStyle = {
          show: false
        };

        item.type = "bar";
        item.stack = "gender";
        item.barCategoryGap = "50px";
        item.barMaxWidth = 60;
        item.barMinWidth = 20;
        isSwapY && (item.yAxisIndex = 1);
        optionFormat.legend.data.push(item.name);
        item.data.forEach((dataItem, dataIndex) => {
          if (totalData[dataIndex]) {
            totalData[dataIndex] += dataItem;
          } else {
            totalData[dataIndex] = dataItem;
          }
        });
        item.label = {
          show:idx==seriesData.length-1,
          color:'#000',
          position:'top',
          formatter(params){
            let num = totalData[params.dataIndex]
            return that.toThousands(num)+ perUnit +'\n'+(num*100/totalNum).toFixed(2)+'%'
          }
        }
      });

      let _colors =
        _color || this.getRandomColors(optionFormat.legend.data.length);
      let coverTemp = {
        color: _colors,
        grid: grid || {
          top: 60,
          right: doubleYaxis ? 60 : 26,
          bottom: 60,
          left: 60
        }
      };
      if (doubleYaxis) {
        coverTemp["yAxis"] = isSwapY
          ? [
              Object.assign({}, optionFormat.yAxis, { name: "%"}),
              optionFormat.yAxis
            ]
          : [
              optionFormat.yAxis,
              Object.assign({}, optionFormat.yAxis, { name: "%" })
            ];
        seriesData.push({
          type: "line",
          name: "rate",
          yAxisIndex: isSwapY ? 0 : 1,
          symbol: "none",
          lineStyle: {
            color: "transparent"
          },
          data: totalData.map(item => {
            return ((item / totalNum) * 100).toFixed(2);
          })
        });
      }
      let option = Object.assign({}, optionFormat, coverTemp);
      option.xAxis.data = legendTempData;
      option.series = seriesData;
      option.tooltip.formatter = (params, ticket, callback) => {
        let htmls = "",
          xaxisName = "",
          ratio = "",
          numRatio = "",
          ageNum = "",
          ageRatioNum = "",
          ageRatio = "",
          ageUnit = "",
          genderUnit = "",
          genderNum = "",
          lang = "";
        if (window.localStorage.getItem("lang")) {
          lang = window.localStorage.getItem("lang");
        }
        if (params.length > 0) {
          xaxisName = params[0].axisValue;
          ageNum =
            ageArr[params[0].dataIndex] || ageArr[params[0].dataIndex] == 0
              ? ageArr[params[0].dataIndex] >= 100000
                ? (ageArr[params[0].dataIndex] / 10000).toFixed(2)
                : ageArr[params[0].dataIndex]
              : "--";
          ageUnit = ageArr[params[0].dataIndex]
            ? ageArr[params[0].dataIndex] >= 100000
              ? this.$t("format.millionTime")
              : perUnit
            : perUnit;
          ageRatioNum = ageArr[params[0].dataIndex] / totalNum;
          ageRatio =
            ageRatioNum == 0 ? "0%" : (ageRatioNum * 100).toFixed(2) + "%";
          htmls +=
            '<div style="font-size:16px;height:32px;color:#0069FF;border-radius:4px;line-height:36px;padding-left:15px;padding-right:15px;text-align: left; overflow: hidden;"><span style="float: left; text-align: left;">' +
            xaxisName +
            "</span>";
          if (lang == "en_US") {
            htmls +=
              '<span style="float: left; width: 100px; text-align: center; padding: 0 10px;">' +
              ageNum +
              ageUnit +
              "</span>";
          } else {
            htmls +=
              '<span style="float: left; width: 80px; text-align: center; padding: 0 10px;">' +
              ageNum +
              ageUnit +
              "</span>";
          }
          htmls +=
            '<span style="float: right; width: 90px; text-align: center;">' +
            ageRatio +
            "</span></div><div>";
          params.forEach(item => {
            if (item.seriesName !== "rate") {
              genderNum =
                params[0].data || params[0].data == 0
                  ? item.data >= 100000
                    ? (item.data / 10000).toFixed(2)
                    : item.data
                  : "--";
              numRatio =
                item.data == 0 || totalData[item.dataIndex] == 0
                  ? 0
                  : item.data / totalData[item.dataIndex];
              genderUnit = item.data
                ? item.data >= 100000
                  ? this.$t("format.millionTime")
                  : perUnit
                : perUnit;
              ratio = numRatio == 0 ? "0%" : (numRatio * 100).toFixed(2) + "%";
              htmls +=
                '<p style="font-size:14px;padding:4px 23px 6px 15px;color:#333;text-align: center; overflow: hidden;"><span style="float: left; text-align: center;">' +
                item.seriesName +
                ':</span><span style="float: right; text-align: center; width: 90px;">' +
                ratio +
                "</span>";
              if (lang == "en_US") {
                htmls +=
                  '<span style="float: right; text-align: center; width: 100px;">' +
                  genderNum +
                  genderUnit +
                  "</span></p>";
              } else {
                htmls +=
                  '<span style="float: right; text-align: center; width: 90px;">' +
                  genderNum +
                  genderUnit +
                  "</span></p>";
              }
            }
          });
          htmls += "</div>";
          return htmls;
        }
      };
      return option;
    }
  },
  created() {

  }
}

</script>
<style scoped>
.chart {
  position: relative;
  height: 500px;
}

</style>