echarts 折線圖拼接

潇可爱❤發表於2024-07-09

效果圖:

<script setup lang="ts">
import * as echarts from 'echarts';
import { ref, watch, nextTick, computed } from 'vue';
import { useRouteParams } from '@/hooks/useRouteParams';
import { queryIncreaseTrend } from '@/api/warning';
import { formatPercent } from '@/utils/util';
import dayjs from 'dayjs';
import moment from 'moment';

const props = defineProps({
  originData: {
    type: Array,
    default: () => {
      return [];
    }
  },
  params: {
    type: Object,
    default: () => {}
  }
});
// @ts-ignore
let myChart: any = null;
const dailyChartRef = ref();
// @ts-ignore
const data1 = ref<any>([]);
// @ts-ignore
const data2 = ref<any>([]);
const dataNames = ref<any>([]);
const statDate = ref<any>([]);

const dateType = ref(props.params.period);
const statDateBegin = ref(props.params.statDateBeginStr);
const statDateEnd = ref(props.params.statDateEndStr);
const curId = ref(props.params.curId);
const DTD = ref(props.params.DTD);
const colors = ['#03B7D9', '#B2B6C5'];

const chartConfig = computed(() => {
  let data11 = [];
  let data12 = [];
  let data21 = [];
  let data22 = [];
  let dateIndex = statDate.value.indexOf(moment(statDateBegin.value).format('YYYYMMDD'));
  data11 = data1.value.map((v, i) => {
    if (i < dateIndex) {
      return undefined;
    } else {
      return v;
    }
  });
  data12 = data1.value.map((v, i) => {
    if (i <= dateIndex) {
      return v;
    } else {
      return undefined;
    }
  });

  data21 = data2.value.map((v, i) => {
    if (i < dateIndex) {
      return undefined;
    } else {
      return v;
    }
  });
  data22 = data2.value.map((v, i) => {
    if (i <= dateIndex) {
      return v;
    } else {
      return undefined;
    }
  });
  return {
    color: colors,
    title: {
      show: false,
      text: '近4周業務增速',
      left: 10,
      textStyle: {
        color: '#303133',
        fontWeight: 500
      },
      padding: [5, 10, 40, 0]
    },
    grid: {
      left: '14%',
      top: '14%',
      right: '10%'
    },
    legend: {
      data: ['增速1', '行業增速'],
      selected: { 增速1: true, 行業增速: true },
      bottom: 10,
      icon: 'rect',
      itemWidth: 10,
      itemHeight: 2
    },
    tooltip: {
      show: true,
      trigger: 'axis',
      // formatter: `{b0}<br/>{a0}: {c0}%<br />{a1}: {c1}%`,
      backgroundColor: 'rgba(50,50,50,0.8)',
      borderColor: 'rgba(57, 56, 56, 0.8)',
      textStyle: {
        color: 'rgba(255, 255, 255, 1)'
      },
      formatter: function (params, ticket, callback) {
        var htmlStr = '';
        var valMap = {};
        for (var i = 0; i < params.length; i++) {
          var param = params[i];
          var xName = param.name; //x軸的名稱
          var seriesName = param.seriesName; //圖例名稱
          var value = param.value; //y軸值
          var color = param.color; //圖例顏色

          //過濾無效值
          if (value == undefined) {
            continue;
          }

          //過濾重疊值
          if (valMap[seriesName] == value) {
            continue;
          }

          if (i === 0) {
            htmlStr += xName + '<br/>'; //x軸的名稱
          }
          htmlStr += '<div>';
          //為了保證和原來的效果一樣,這裡自己實現了一個點的效果
          htmlStr +=
            '<span style="margin-right:5px;display:inline-block;width:10px;height:10px;border-radius:5px;background-color:' +
            color +
            ';"></span>';

          //圓點後面顯示的文字
          htmlStr += seriesName + '' + value;

          htmlStr += '</div>';
          valMap[seriesName] = value;
        }
        return htmlStr;
      }
    },
    xAxis: [
      {
        type: 'category',
        axisTick: {
          alignWithLabel: true
        },
        data: [],
        axisLabel: {
          // rotate: 0, // 旋轉標籤,根據實際情況調整角度
          // margin: 20, // 標籤與軸線之間的距離
          interval: 0 // 強制顯示所有標籤
        },
        boundaryGap: false
      }
    ],
    yAxis: [
      {
        type: 'value',
        name: '率值',
        position: 'left',
        // min: 0,
        // axisLine: {
        //   show: false
        // },
        axisLabel: {
          formatter: '{value}%'
        }
      }
    ],
    series: [
      {
        name: '增速1',
        type: 'line',
        data: data11,
        symbolSize: 0,
        smooth: true,
        color: '#03B7D9'
      },
      {
        name: '增速1',
        type: 'line',
        data: data12,
        symbolSize: 0,
        smooth: true,
        color: '#B2B6C5'
      },
      {
        name: '行業增速',
        type: 'line',
        data: data21,
        symbolSize: 0,
        smooth: true,
        color: 'rgba(63, 103, 229, 1)'
      },
      {
        name: '行業增速',
        type: 'line',
        data: data22,
        symbolSize: 0,
        smooth: true,
        color: '#B2B6C5'
      }
    ]
  };
});

const initChart = () => {
  if (dailyChartRef.value) {
    // @ts-ignore
    if (!myChart) {
      myChart = echarts.init(dailyChartRef.value);
    } else {
      // @ts-ignore
      myChart.clear();
    }

    chartConfig.value.xAxis[0].data = dataNames.value;
    myChart && myChart.setOption(chartConfig.value);
    setTimeout(() => {
      myChart && myChart.resize();
    }, 1000);
    myChart.on('legendselectchanged', function (params: any) {
      let option = chartConfig.value;
      let selected_value = Object.values(params.selected);
      if (selected_value.every((val) => !val)) {
        option.legend[0].selected[params.name] = true;
      }

      myChart.setOption(option);
    });
  }
};

const init = async () => {
  const commonParams = {
    manageAreaId: curId.value,
    queryType: dateType.value,
    startTimeStr: dayjs(statDateBegin.value).format('YYYY/MM/DD'),
    endTimeStr: dayjs(statDateEnd.value).format('YYYY/MM/DD')
  };
  console.log(commonParams);
  let res: any = await queryIncreaseTrend(commonParams);
  dataNames.value = [];
  statDate.value = [];
  data1.value = [];
  data2.value = [];
  if (res) {
    res.forEach((item: any, index: number) => {
      statDate.value[index] = item.statDate;
      dataNames.value[index] = item.timeSection;
      data1.value[index] = formatPercent(item.ztoIncreaseRate, 2, false);
      data2.value[index] = formatPercent(item.industryIncreaseRate, 2, false);
    });
  }

  nextTick(() => {
    initChart();
  });
};

watch(
  () => props.params,
  (val, oldVal) => {
    if (val) {
      // if (val.statDateBeginStr == val.statDateEndStr) return
      console.log(val);
      dateType.value = val.period;
      statDateBegin.value = val.statDateBeginStr;
      statDateEnd.value = val.statDateEndStr;
      DTD.value = val.DTD;

      if (val.curId) {
        curId.value = Number(val.curId);
      }
      init();
    }
  },
  {
    // immediate: true,
    deep: true
  }
);
</script>

<template>
  <div class="line-box">
    <div class="title">業務增速近7天趨勢</div>
    <div ref="dailyChartRef" class="line-echarts"></div>
  </div>
</template>

<style scoped lang="scss">
.line-box {
  background: #fff;
  border-radius: 8px;
  color: #303133;
  padding-top: 16px;

  //padding: 16px;
  .title {
    font-size: 17px;
    font-weight: bold;
    padding-left: 16px;

    .text {
      font-size: 13px;
    }
  }

  .line-echarts {
    width: 100%;
    height: 220px;
  }
}
</style>

相關文章