分类别柱状图(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>
相关推荐
kyriewen1 天前
别再对着 TypeScript 报错发呆了:我把 10 个最常见的红色波浪线翻译成了人话
前端·javascript·typescript
妙码生花2 天前
现代前端的极致性能 icon 加载方案(死磕成功版)
前端·vue.js·typescript
MonkeyKing2 天前
鸿蒙ArkTS深度剖析:ArkTS与TS/JS核心差异、静态强类型实战优势
typescript·harmonyos
Momo__4 天前
TypeScript satisfies 操作符——比 as 更安全的类型守门员
前端·typescript
Awu12275 天前
⚡从零开发 Agent CLI(四):给 CLI 装上"LLM 引擎"
typescript·ai编程·claude
假如让我当三天老蒯6 天前
TypeScript 继续学习(学习用)
前端·面试·typescript
一份执念6 天前
ECharts 安装与使用完全指南:从全量引入到小程序分包优化
微信小程序·echarts
一份执念7 天前
uni-app项目 (vue+vite + uni-UI)中引入umd格式JS文件,微信小程序中导入报错处理方案
前端·uni-app·echarts
糖拌西瓜皮7 天前
Node.js工程化实践:包管理、TypeScript配置与代码质量
typescript·node.js
Bolt8 天前
TypeScript 7.0 来了:当 tsc 用 Go 重写之后
javascript·typescript·go