Skip to content

Chart 图表

基于 ECharts 的专业图表组件,支持所有 ECharts 图表类型,提供赛博朋克风格的霓虹发光效果。

基础用法

最简单的图表用法。

vue
<template>
  <ex-chart :option="lineOption" height="300px" />
</template>

<script setup>
import { ref } from 'vue';

const lineOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [120, 200, 150, 80, 70, 110, 130],
      type: 'line',
      smooth: true,
    },
  ],
});
</script>

柱状图

使用柱状图展示数据。

vue
<template>
  <ex-chart :option="barOption" height="300px" />
</template>

<script setup>
import { ref } from 'vue';

const barOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [120, 200, 150, 80, 70, 110, 130],
      type: 'bar',
    },
  ],
});
</script>

饼图

使用饼图展示占比数据。

vue
<template>
  <ex-chart :option="pieOption" height="300px" />
</template>

<script setup>
import { ref } from 'vue';

const pieOption = ref({
  series: [
    {
      type: 'pie',
      radius: '50%',
      data: [
        { value: 1048, name: 'Search Engine' },
        { value: 735, name: 'Direct' },
        { value: 580, name: 'Email' },
        { value: 484, name: 'Union Ads' },
        { value: 300, name: 'Video Ads' },
      ],
    },
  ],
});
</script>

散点图

使用散点图展示分布数据。

vue
<template>
  <ex-chart :option="scatterOption" height="300px" />
</template>

<script setup>
import { ref } from 'vue';

const scatterOption = ref({
  xAxis: {},
  yAxis: {},
  series: [
    {
      type: 'scatter',
      data: [
        [10, 8.04],
        [8, 6.95],
        [13, 7.58],
        [9, 8.81],
        [11, 8.33],
        [14, 9.96],
        [6, 7.24],
        [4, 4.26],
        [12, 10.84],
        [7, 4.82],
        [5, 5.68],
      ],
    },
  ],
});
</script>

雷达图

使用雷达图展示多维数据。

vue
<template>
  <ex-chart :option="radarOption" height="300px" />
</template>

<script setup>
import { ref } from 'vue';

const radarOption = ref({
  tooltip: {
    trigger: 'item',
  },
  legend: {
    data: ['预算分配', '实际支出'],
    bottom: 0,
  },
  radar: {
    indicator: [
      { name: '销售', max: 7000 },
      { name: '行政', max: 16000 },
      { name: '信息技术', max: 30000 },
      { name: '客户支持', max: 40000 },
      { name: '研发', max: 55000 },
      { name: '市场', max: 25000 },
    ],
    splitNumber: 5,
    // 禁用 alignTicks 避免刻度不可读警告
    alignTicks: false,
  },
  series: [
    {
      type: 'radar',
      data: [
        {
          value: [4200, 3000, 20000, 35000, 50000, 18000],
          name: '预算分配',
          areaStyle: { opacity: 0.3 },
        },
        {
          value: [5000, 14000, 28000, 26000, 42000, 21000],
          name: '实际支出',
          areaStyle: { opacity: 0.3 },
        },
      ],
    },
  ],
});
</script>

平滑面积图

弧形折线配合渐变填充,常用于趋势展示。

vue
<template>
  <ex-chart :option="areaLineOption" height="300px" />
</template>

<script setup>
import { ref } from 'vue';

const areaLineOption = ref({
  tooltip: { trigger: 'axis' },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
  },
  yAxis: { type: 'value' },
  series: [
    {
      data: [820, 932, 901, 934, 1290, 1330, 1320],
      type: 'line',
      smooth: true,
      lineStyle: { width: 3 },
      areaStyle: {
        color: {
          type: 'linear',
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: [
            { offset: 0, color: 'rgba(41, 171, 226, 0.55)' },
            { offset: 1, color: 'rgba(41, 171, 226, 0.02)' },
          ],
        },
      },
    },
  ],
});
</script>

动态实时折线

通过定时替换 option 实现实时数据流动效果(每秒推入一个新数据点)。

vue
<template>
  <ex-chart :option="dynamicLineOption" height="300px" />
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';

const data = Array.from({ length: 20 }, (_, i) => Math.round(60 + Math.sin(i / 3) * 30));
const time = Array.from({ length: 20 }, (_, i) => `${i}s`);
let cursor = 20;

const build = () => ({
  tooltip: { trigger: 'axis' },
  xAxis: { type: 'category', boundaryGap: false, data: [...time] },
  yAxis: { type: 'value', max: 140 },
  series: [
    {
      type: 'line',
      smooth: true,
      showSymbol: false,
      data: [...data],
      areaStyle: { opacity: 0.15 },
    },
  ],
});

const dynamicLineOption = ref(build());
let timer;
onMounted(() => {
  timer = setInterval(() => {
    data.shift();
    data.push(Math.round(60 + Math.sin(cursor / 3) * 30 + Math.random() * 20));
    time.shift();
    time.push(`${cursor}s`);
    cursor++;
    dynamicLineOption.value = build(); // 替换引用触发更新
  }, 1000);
});
onUnmounted(() => clearInterval(timer));
</script>

仪表盘

使用仪表盘展示进度数据。

vue
<template>
  <ex-chart :option="gaugeOption" height="300px" />
</template>

<script setup>
import { ref } from 'vue';

const gaugeOption = ref({
  series: [
    {
      type: 'gauge',
      progress: {
        show: true,
      },
      detail: {
        valueAnimation: true,
        formatter: '{value}%',
      },
      data: [{ value: 75, name: 'Progress' }],
    },
  ],
});
</script>

完整配置

展示包含标题、图例、工具栏、提示框的完整图表。

vue
<template>
  <ex-chart :option="fullOption" height="400px" />
</template>

<script setup>
import { ref } from 'vue';

const fullOption = ref({
  title: {
    text: '销售数据统计',
    subtext: '2024年度',
    left: 'center',
  },
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: 'cross',
    },
  },
  legend: {
    data: ['销售额', '利润'],
    bottom: 10,
  },
  toolbox: {
    show: true,
    feature: {
      saveAsImage: { title: '保存为图片' },
      dataView: { title: '数据视图', readOnly: false },
      restore: { title: '还原' },
      dataZoom: { title: { zoom: '区域缩放', back: '还原缩放' } },
      magicType: {
        title: { line: '切换为折线图', bar: '切换为柱状图' },
        type: ['line', 'bar'],
      },
    },
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '15%',
    top: '15%',
    containLabel: true,
  },
  xAxis: {
    type: 'category',
    data: ['1月', '2月', '3月', '4月', '5月', '6月'],
    name: '月份',
    nameLocation: 'middle',
    nameGap: 30,
  },
  yAxis: {
    type: 'value',
    name: '金额(万元)',
    nameLocation: 'middle',
    nameGap: 50,
  },
  series: [
    {
      name: '销售额',
      type: 'bar',
      data: [120, 200, 150, 80, 70, 110],
    },
    {
      name: '利润',
      type: 'line',
      data: [60, 100, 75, 40, 35, 55],
      smooth: true,
    },
  ],
});
</script>

加载状态

显示图表加载动画。

vue
<template>
  <ex-space direction="vertical" style="width: 100%">
    <ex-button @click="loading = !loading">
      {{ loading ? '隐藏加载' : '显示加载' }}
    </ex-button>
    <ex-chart :option="lineOption" :loading="loading" loading-text="数据加载中..." height="300px" />
  </ex-space>
</template>

<script setup>
import { ref } from 'vue';

const loading = ref(false);

const lineOption = ref({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  yAxis: {
    type: 'value',
  },
  series: [
    {
      data: [120, 200, 150, 80, 70, 110, 130],
      type: 'line',
      smooth: true,
    },
  ],
});
</script>

空状态

当没有数据时显示空状态。

vue
<template>
  <ex-chart :option="emptyOption" height="300px" />
</template>

<script setup>
import { ref } from 'vue';

const emptyOption = ref({
  series: [],
});
</script>

不同尺寸

提供三种尺寸的图表。

vue
<template>
  <ex-chart :option="lineOption" size="small" height="200px" />
  <ex-chart :option="lineOption" size="medium" height="300px" />
  <ex-chart :option="lineOption" size="large" height="400px" />
</template>

事件处理

监听图表事件。

vue
<template>
  <ex-chart :option="lineOption" height="300px" @click="handleClick" @finished="handleFinished" />
</template>

<script setup>
const handleClick = params => {
  console.log('Chart clicked:', params);
};

const handleFinished = () => {
  console.log('Chart render finished');
};
</script>

API

Props

参数说明类型可选值默认值
optionECharts 配置选项EChartsOption
type图表类型(用于预设配置)stringline / bar / pie / scatter / radar / gauge / funnel / candlestick / heatmap / tree / treemap / sunburst / graph / sankey / boxplot / parallel / custom
size图表尺寸stringsmall / medium / largemedium
width图表宽度string / number100%
height图表高度string / number400px
loading是否显示加载动画booleanfalse
loading-text加载文本string
auto-resize是否自动调整大小booleantrue
resize-delay调整大小防抖延迟(毫秒)number300
show-toolbox是否显示工具栏booleanfalse
show-data-zoom是否显示数据缩放booleanfalse
show-legend是否显示图例booleantrue
show-tooltip是否显示提示框booleantrue
show-grid是否显示网格booleantrue
animation-duration动画时长(毫秒)number1000
renderer图表渲染器stringcanvas / svgcanvas
init-options初始化配置EChartsInitOpts
aria-label无障碍标签string

Events

事件名说明回调参数
init图表初始化完成(instance: ECharts)
click图表点击事件(params: ECElementEvent)
dblclick图表双击事件(params: ECElementEvent)
mouseover图表鼠标移入事件(params: ECElementEvent)
mouseout图表鼠标移出事件(params: ECElementEvent)
mousemove图表鼠标移动事件(params: ECElementEvent)
datazoom图表数据缩放事件(params: ECElementEvent)
legendselectchanged图表图例选择改变事件(params: ECElementEvent)
finished图表渲染完成事件
updated图表更新完成事件
error图表错误事件(error: Error)

Methods

方法名说明参数
getInstance获取 ECharts 实例
getElement获取图表 DOM 元素
resize手动调整图表大小(opts?: ResizeOpts)
clear清空图表
dispose销毁图表实例
setOption设置图表配置(option: EChartsOption, opts?: SetOptionOpts)
showLoading显示加载动画(type?: string, opts?: object)
hideLoading隐藏加载动画
getDataURL获取图表数据 URL(opts?: object)
getSvgDataURL获取图表 SVG 字符串
convertToPixel转换坐标(finder: ConvertFinder, value: unknown)
convertFromPixel转换坐标(finder: ConvertFinder, value: unknown)

Slots

插槽名说明
empty自定义空状态内容