SeviceRatioChart.vue 4.89 KB
<template>
  <div id="SeviceRatio"></div>
</template>

<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';

export default {
  name: 'SeviceRatio',
  mixins: [chartMixin],
  props: {
    changeServiceHandle: {
      type: Function,
    },
  },
  data() {
    let totle = this.data.reduce((count, item) => count + item.count, 0);
    return {
      totle: totle,
      percentDom: null,
      serviceNameDom: null,
      SelectedDataIndex: null,
    };
  },
  mounted() {
    this.initChart();
  },
  methods: {
    initChart() {
      this.totle = this.data.reduce((count, item) => count + item.count, 0);
      this.chart = new G2.Chart({
        container: 'SeviceRatio',
        forceFit: true,
        height: this.height - 30,
        padding: [0, 220, 0, 0],
      });
      this.chart.source(this.data);
      this.chart.coord('theta', {
        radius: 0.9,
        innerRadius: 0.75,
      });
      this.chart.tooltip(false);
      // 图例
      this.chart.legend({
        position: 'right-center',
        marker: 'square',
        clickable: false,
        offsetX: -2,
        useHtml: true,
        containerTpl: `
         <div class="g2-legend">
          <ul class="g2-legend-list" style="list-style-type:none;margin:0;padding:0;"></ul>
         </div>`,
        itemTpl: (value, color, checked, index) => {
          const obj = this.data[index];
          checked = checked ? 'checked' : 'unChecked';
          let price = this.$formatPrice(obj.count);
          return `
            <li
              class="g2-legend-list-item item-${index} ${checked}"
              data-value="${value}"
              data-color=${color}
              style="cursor: pointer;font-size:14px;width:100%;"
            >
              <i
                class="g2-legend-marker"
                style="display:inline-block;margin-right:10px;background-color:${color};"
              ></i>
              <span class="g2-legend-text" title="${value}">${value}:</span>
              <span class="g2-legend-price">${price}</span>元
            </li>
            `;
        },
        'g2-legend': {
          width: '215px',
          'max-width': '215px',
          // left: '-20px',
        },
        'g2-legend-list-item': {
          color: '#333',
        },
        'g2-legend-marker': {
          width: '10px',
          height: '5px',
          borderRadius: 'none',
        },
      });
      // 坐标系及着色
      this.chartGeom = this.chart
        .intervalStack()
        .position('count')
        .color('serviceName', [
          '#4e82fb',
          '#fb774e',
          '#ffc934',
          '#41bf52',
          '#9b50ff',
          '#94de70',
          '#b5593d',
          '#fe8787',
          '#254eae',
          '#2f4554',
        ]);

      // 辅助元素
      this.chart.guide().html({
        position: ['50%', '50%'],
        html: `<div class="SeviceRatio-centerText">
            <span class="SeviceRatio-percent">0.00</span>%<br>
            <span class="SeviceRatio-serviceName"></span>
        </div>`,
        alignX: 'middle',
        alignY: 'middle',
      });
      this.chart.render();
      this.chart.on('interval:click', this.clickHandle);
    },
    updateData() {
      if (this.data.length) {
        this.totle = this.data.reduce((count, item) => count + item.count, 0);
        this.chartGeom.setSelected(this.data[0]);
        this.changeSelected(this.data[0]);
        this.SelectedDataIndex = this.data[0];
      }
    },
    clickHandle(ev) {
      let data = ev.data._origin;
      if (this.SelectedDataIndex.serviceId !== data.serviceId) {
        this.SelectedDataIndex = data;
        this.changeSelected(data);
        this.changeServiceHandle(data);
      }
    },
    changeSelected(data) {
      this.percentDom = document.querySelector('.SeviceRatio-percent');
      this.serviceNameDom = document.querySelector('.SeviceRatio-serviceName');

      if (this.percentDom) {
        if (this.total === 0) {
          this.percentDom.innerHTML = '0.00';
        } else {
          this.percentDom.innerHTML = ((data.count / this.totle) * 100).toFixed(
            2
          );
        }
      }
      if (this.serviceNameDom) {
        this.serviceNameDom.innerHTML = data.serviceName;
      }
    },
  },
};
</script>

<style lang="scss">
@import '@/assets/styles/variables.scss';
#SeviceRatio {
  .g2-legend-text {
    display: inline-block;
    width: 90px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
  }
  .SeviceRatio-centerText {
    color: #333;
    font-size: 20px;
    text-align: center;
  }
  .SeviceRatio-serviceName {
    font-size: 16px;
  }
  .g2-legend-price {
    display: inline-block;
    width: 86px;
    text-align: right;
  }
}
@media screen and (max-width: $bigScreenWidth) {
  #SeviceRatio {
    .SeviceRatio-centerText {
      font-size: 16px;
    }
    .SeviceRatio-serviceName {
      font-size: 14px;
    }
  }
}
</style>