F2图例封装 - Pie

基于vue3 和 F2 3.5.0

<template>
  <div :style="{minHeight: `${height}px`,width: '100%' }" ref="container">
    <canvas v-show="showChart" ref="canvas" :id="chartId" class="chart-canval"></canvas>
    <empty-box v-show="!showChart"></empty-box>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import F2 from '@antv/f2/lib/index-all.js';
import { flame } from "ionicons/icons";
import {isArray, sumBy} from 'lodash-es';

const props = defineProps({
  height: {
    type: Number,
    default: 260,
    required: false
  },
  chartId: {
    type: String,
    default: 'PieChart'
  },
  legendPosition: {
    type: String,
    default: 'bottom'
  },
  color: {
    type: Array,
    default: ['#F0BD58', '#97DFD8', '#ED7E63', '#7357F6', '#84BBF0FF', '#D364BBFF', '#459EF5FF', '#71D364FF', '#F5D18AFF', '#A1E498FF']
  },
  labelInto: {
    type: String,
    default: ''
  },
  unit: {
    type: String,
    default: ''
  },
  showLegendUnit: {
    type: Boolean,
    default: false
  },
  showLegend: {
    type: Boolean,
    default: true
  },
  showPieLabel: {
    type: Boolean,
    default: false
  },
  pieLabelSidePadding: {
    type: Number,
    default: 15
  },
  intervalPositionX: {
    type: String,
    default: 'name'
  },
  intervalPositionY: {
    type: String,
    default: 'number'
  },
})

const chart = ref()
const canvas = ref()
const container = ref()
const showChart = ref(true)

onMounted(() => {
  setTimeout(() => {
    newChartBox()
  }, 100);
})

const newChartBox = () => {
  const clientWidth = document.documentElement.clientWidth
  const domWidth = container.value.clientWidth
  chart.value = new F2.Chart({
    id: props.chartId,
    width: domWidth || clientWidth,
    height: props.height,
    // padding: [10, 10, 100, 30],
    pixelRatio: window.devicePixelRatio
  });
}

/**
 * @description: 饼图
 * @param {*} data 数据
 * @return {*}
 */
const initChartTimeout = (data: any, labelNumber?: any) => {
  if (data.length > 0) {
    showChart.value = true;

    const mapNum: any = {};
    const mapRate: any = {};
    const totalNum: any = Number(sumBy(data, props.intervalPositionY).toFixed(2))

    if (isArray(data)) {
      data.forEach(function (obj) {
        mapNum[obj[props.intervalPositionX]] = obj[props.intervalPositionY];
      });
      data.forEach(function (obj) {
        if ( obj['ratio'] ) {
          mapRate[obj[props.intervalPositionX]] = obj.ratio;
        } else {
          const ratio: any = Number((obj[props.intervalPositionY] / totalNum * 100).toFixed(2));
          obj['ratio'] = ratio;
          mapRate[obj[props.intervalPositionX]] = ratio;
        }
      });
    }

    if (chart.value) {
      chart.value.clear(); // 清理所有
    }
    chart.value.source(data);
    chart.value.tooltip(false);
    chart.value.coord('polar', {
      transposed: true,
      innerRadius: 0.75,
      radius: 0.95
    });

    chart.value.axis(false);

    chart.value.interval()
      .position(`const*ratio`)
      .color([props.intervalPositionX], props.color)
      .adjust('stack');

    if (props.showLegend) {
      chart.value.legend({
        position: props.legendPosition,
        align: 'center',
        itemWidth: null,
        itemFormatter: (val: any) => {
          if (props.showLegendUnit) {
            return `${val}    ${mapNum[val]}${props.unit}   ${mapRate[val]}%`;
          } else {
            return `${val}    ${mapNum[val]}${props.unit}`;
          }
        }
      })
    } else {
      chart.value.legend(false);
    }

    if (labelNumber || props.labelInto) {
      chart.value.guide().html({
        position: ['50%', '50%'],
        html: `<div style="width: 120px;;text-align: center;">
            <div style="font-size: 16px;font-weight:600;">${totalNum || ''}</div>
            <div style="font-size: 12px">${props.labelInto || ''}</div>
                </div>`
      });
    }

    if (props.showPieLabel) {
      chart.value.pieLabel({
        sidePadding: props.pieLabelSidePadding,
        label1: function label1(data: any) {
          return {
            text: data[props.intervalPositionX],
            fill: '#808080',
          };
        },
        label2: function label2(data: any) {
          return {
            fill: '#000000',
            text: `${data[props.intervalPositionY]}   ${data.ratio}%`,
            fontWeight: 500,
            fontSize: 10,
          };
        }
      });
    }
    render()
  } else {
    showChart.value = false
  }
}

const initChart = (data: any, labelNumber?: any) => {
  setTimeout(() => {
    initChartTimeout(data, labelNumber)
  }, 100);
}

const render = () => {
  chart.value.render();
}

defineExpose({ initChart, chart, render, newChartBox })

</script>

引用

<InitPieChart ref="refPieChart" chartId="refPieChart" :height="220" unit="户" label-into="总户数"/>
const initChart = () => {
  let chartData = [
    {number: 0, name: '农户', const: 'const', prop: 'subjectNumFarm'},
    {number: 0, name: '商户', const: 'const', prop: 'subjectNumMerc'},
    {number: 0, name: '企业', const: 'const', prop: 'subjectNumEnt'},
    {number: 0, name: '其他', const: 'const', prop: 'subjectNumOth'}
  ]
  chartData = chartData.map(item => ({
    ...item,
    number: houseData.value[item.prop]
  }));
  refPieChart.value.initChart(chartData)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值