分类别柱状图(Vue3)
效果图:
需求:男女年龄段占比
<template><div class="go-ClassifyBar01"><v-chartref="vChartRef":option="option"style="width: 100%; height: 800px"></v-chart></div>
</template><script setup lang="ts">
import { ref, reactive, watch, onMounted } from "vue";
import VChart from "vue-echarts";
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { BarChart } from "echarts/charts";
import {GridComponent,TooltipComponent,LegendComponent,
} from "echarts/components";use([CanvasRenderer,BarChart,GridComponent,TooltipComponent,LegendComponent,
]);// 获取图表实例
const vChartRef = ref();// 定义数据类型
interface ChartDataItem {name: string;data: Array<{value: number;label: string;}>;
}// 模拟接口数据数组
const chartData = ref<ChartDataItem[]>([{name: "男性",data: [{ value: 5, label: "小于1岁" },{ value: 12, label: "1 ~ 9 岁" },{ value: 10, label: "10 ~ 19 岁" },{ value: 7, label: "20 ~ 29 岁" },{ value: 32, label: "30 ~ 39 岁" },{ value: 40, label: "40 ~ 49 岁" },{ value: 28, label: "50 ~ 59 岁" },{ value: 34, label: "大于60岁" },],},{name: "女性",data: [{ value: 8, label: "小于1岁" },{ value: 15, label: "1 ~ 9 岁" },{ value: 13, label: "10 ~ 19 岁" },{ value: 9, label: "20 ~ 29 岁" },{ value: 35, label: "30 ~ 39 岁" },{ value: 38, label: "40 ~ 49 岁" },{ value: 25, label: "50 ~ 59 岁" },{ value: 30, label: "大于60岁" },],},
]);const option = reactive({// 图位置定制grid: [{left: "12%",width: "28%",containLabel: true,bottom: 30,top: 30,},{left: "50%",width: "0%",bottom: 46,top: 30,},{right: "12%",width: "28%",containLabel: true,bottom: 30,top: 30,},],legend: {show: true,left: "center",top: 0,data: <any>[],},xAxis: [{type: "value",inverse: true,axisLabel: {show: true,color: "#000",margin: 8,},axisLine: {show: true,},axisTick: {show: false,},splitLine: {show: true,lineStyle: {type: "dashed",},},},{gridIndex: 1,show: true,splitLine: {show: true,lineStyle: {type: "dashed",},},axisLabel: {show: true,color: "#000",margin: 0,},},{gridIndex: 2,type: "value",axisLabel: {show: true,color: "#000",margin: 8,},axisLine: {show: true,},axisTick: {show: false,},splitLine: {show: true,lineStyle: {type: "dashed",},},},],yAxis: [{type: "category",position: "right",inverse: false,axisLine: {show: true,},axisTick: {show: false,},axisLabel: {show: false,},data: <any>[],},{type: "category",inverse: false,gridIndex: 1,position: "center",axisLabel: {align: "center",padding: [8, 0, 0, 0],fontSize: 12,color: "#000",},axisLine: {show: false,},axisTick: {show: false,},data: <any>[],},{type: "category",inverse: false,gridIndex: 2,position: "left",axisLabel: {show: false,},axisLine: {show: true,},axisTick: {show: false,},data: <any>[],},],series: [] as any[],
});// 更新图表数据
const updateChart = () => {if (!chartData.value.length) return;// 更新图例数据option.legend.data = chartData.value.map((item) => item.name);// 提取y轴标签(年龄段)const yAxisData = chartData.value[0].data.map((item) => item.label);// 更新y轴数据option.yAxis[0].data = yAxisData;option.yAxis[1].data = yAxisData;option.yAxis[2].data = yAxisData;// 动态生成系列数据option.series = chartData.value.map((item, index) => {if (index === 0) {return {type: "bar",name: item.name,barWidth: 12,label: {show: true,position: "left",color: "#000",fontWeight: "BoldMT",fontFamily: "Arial-BoldMT",fontSize: 14,formatter: "{c}%",},itemStyle: {color: "#0674F1FF",borderRadius: 0,},data: item.data.map((d) => d.value),};} else {return {xAxisIndex: 2,yAxisIndex: 2,type: "bar",name: item.name,barWidth: 12,label: {show: true,position: "right",color: "#000",fontWeight: "BoldMT",fontFamily: "Arial-BoldMT",fontSize: 14,formatter: "{c}%",},itemStyle: {color: "#E851B3FF",borderRadius: 0,},data: item.data.map((d) => d.value),};}});
};// 监听数据变化
watch(chartData,() => {updateChart();},{ immediate: true }
);// 组件挂载后更新图表
onMounted(() => {updateChart();
});
</script><style scoped>
.go-ClassifyBar01 {width: 100%;height: 100%;
}
</style>