分类别柱状图(Vue3)

效果图:

需求:男女年龄段占比

html 复制代码
<template>
  <div class="go-ClassifyBar01">
    <v-chart
      ref="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>
相关推荐
一只小风华~2 小时前
Vue:条件渲染 (Conditional Rendering)
前端·javascript·vue.js·typescript·前端框架
大虾写代码4 小时前
vue3+TS项目配置Eslint+prettier+husky语法校验
前端·vue·eslint
Pu_Nine_97 小时前
10 分钟上手 ECharts:从“能跑”到“生产级”的完整踩坑之旅
前端·javascript·echarts·css3·html5
烛阴10 小时前
【TS 设计模式完全指南】用适配器模式优雅地“兼容”一切
javascript·设计模式·typescript
叫我阿柒啊12 小时前
从Java全栈到前端框架的实战之路
java·数据库·微服务·typescript·前端框架·vue3·springboot
Spider_Man14 小时前
打造属于你的前端沙盒 🎉
前端·typescript·github
机构师14 小时前
<uniapp><指针组件>基于uniapp,编写一个自定义箭头指针组件
javascript·uni-app·vue·html
小白_ysf14 小时前
uniapp和vue3项目中引入echarts 、lime-echart(微信小程序、H5等)
微信小程序·uni-app·echarts·h5·lime-echart
@AfeiyuO16 小时前
vue3 实现将页面生成 pdf 导出(html2Canvas + jspdf)
前端·pdf·vue