基于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)
}