VbenChart 图表组件
基于 ECharts 的图表组件,支持多种图表类型和响应式布局。
基础用法
vue
<script setup lang="ts">
import { VbenChart } from '@vben/common-ui'
import type { EChartsOption } from 'echarts'
const option: EChartsOption = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}
]
}
</script>
<template>
<VbenChart :option="option" height="400px" />
</template>柱状图
vue
<script setup lang="ts">
import { VbenChart } from '@vben/common-ui'
import type { EChartsOption } from 'echarts'
const option: EChartsOption = {
title: {
text: '月度销售额'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月']
},
yAxis: {
type: 'value'
},
series: [
{
name: '销售额',
type: 'bar',
data: [120, 200, 150, 80, 70, 110],
itemStyle: {
color: '#1890ff'
}
}
]
}
</script>
<template>
<VbenChart :option="option" height="400px" />
</template>饼图
vue
<script setup lang="ts">
import { VbenChart } from '@vben/common-ui'
import type { EChartsOption } from 'echarts'
const option: EChartsOption = {
title: {
text: '用户来源',
left: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
name: '访问来源',
type: 'pie',
radius: '50%',
data: [
{ value: 1048, name: '搜索引擎' },
{ value: 735, name: '直接访问' },
{ value: 580, name: '邮件营销' },
{ value: 484, name: '联盟广告' },
{ value: 300, name: '视频广告' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
</script>
<template>
<VbenChart :option="option" height="400px" />
</template>折线图
vue
<script setup lang="ts">
import { VbenChart } from '@vben/common-ui'
import type { EChartsOption } from 'echarts'
const option: EChartsOption = {
title: {
text: '温度变化'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['最高气温', '最低气温']
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value} °C'
}
},
series: [
{
name: '最高气温',
type: 'line',
data: [11, 11, 15, 13, 12, 13, 10],
smooth: true
},
{
name: '最低气温',
type: 'line',
data: [1, -2, 2, 5, 3, 2, 0],
smooth: true
}
]
}
</script>
<template>
<VbenChart :option="option" height="400px" />
</template>API
Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| option | ECharts 配置项 | EChartsOption | - |
| height | 图表高度 | string | number | '400px' |
| width | 图表宽度 | string | number | '100%' |
| theme | 主题 | string | object | - |
| loading | 是否显示加载动画 | boolean | false |
| loadingOption | 加载动画配置 | object | - |
| autoResize | 是否自动调整大小 | boolean | true |
Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| click | 点击事件 | (params: any) => void |
| dblclick | 双击事件 | (params: any) => void |
| mouseover | 鼠标移入事件 | (params: any) => void |
| mouseout | 鼠标移出事件 | (params: any) => void |
| legendselectchanged | 图例选择变化 | (params: any) => void |
Methods
| 方法名 | 说明 | 参数 |
|---|---|---|
| setOption | 设置图表配置 | (option: EChartsOption, notMerge?: boolean) => void |
| resize | 调整图表大小 | () => void |
| clear | 清空图表 | () => void |
| dispose | 销毁图表实例 | () => void |
| getDataURL | 获取图表图片 | () => string |
完整示例
vue
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { VbenChart } from '@vben/common-ui'
import type { EChartsOption } from 'echarts'
const chartRef = ref()
const loading = ref(true)
const option = ref<EChartsOption>({
title: {
text: '销售数据统计',
left: 'center'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
legend: {
data: ['销售额', '利润'],
top: 30
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
},
yAxis: {
type: 'value'
},
series: [
{
name: '销售额',
type: 'line',
stack: 'Total',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(24, 144, 255, 0.8)' },
{ offset: 1, color: 'rgba(24, 144, 255, 0.1)' }
]
}
},
emphasis: {
focus: 'series'
},
data: [140, 232, 101, 264, 90, 340, 250, 180, 200, 220, 180, 240]
},
{
name: '利润',
type: 'line',
stack: 'Total',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(82, 196, 26, 0.8)' },
{ offset: 1, color: 'rgba(82, 196, 26, 0.1)' }
]
}
},
emphasis: {
focus: 'series'
},
data: [120, 182, 191, 234, 290, 330, 310, 201, 154, 190, 330, 410]
}
]
})
onMounted(async () => {
// 模拟数据加载
await new Promise(resolve => setTimeout(resolve, 1000))
loading.value = false
})
const handleClick = (params: any) => {
console.log('点击:', params)
}
const handleDownload = () => {
const url = chartRef.value?.getDataURL()
const link = document.createElement('a')
link.href = url
link.download = 'chart.png'
link.click()
}
const handleRefresh = async () => {
loading.value = true
// 重新加载数据
await new Promise(resolve => setTimeout(resolve, 1000))
loading.value = false
}
</script>
<template>
<div class="chart-container">
<div class="chart-header">
<h3>销售数据统计</h3>
<a-space>
<a-button @click="handleRefresh">刷新</a-button>
<a-button @click="handleDownload">下载</a-button>
</a-space>
</div>
<VbenChart
ref="chartRef"
:option="option"
:loading="loading"
height="500px"
@click="handleClick"
/>
</div>
</template>
<style scoped>
.chart-container {
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.chart-header h3 {
margin: 0;
font-size: 18px;
font-weight: 600;
}
</style>响应式图表
vue
<script setup lang="ts">
import { ref, computed } from 'vue'
import { VbenChart } from '@vben/common-ui'
import { useWindowSize } from '@vueuse/core'
import type { EChartsOption } from 'echarts'
const { width } = useWindowSize()
const option = computed<EChartsOption>(() => ({
title: {
text: '响应式图表',
left: 'center',
textStyle: {
fontSize: width.value < 768 ? 14 : 18
}
},
grid: {
left: width.value < 768 ? '10%' : '3%',
right: width.value < 768 ? '10%' : '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
axisLabel: {
fontSize: width.value < 768 ? 10 : 12
}
},
yAxis: {
type: 'value',
axisLabel: {
fontSize: width.value < 768 ? 10 : 12
}
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line',
smooth: true
}
]
}))
</script>
<template>
<VbenChart :option="option" height="400px" />
</template>主题定制
vue
<script setup lang="ts">
import { VbenChart } from '@vben/common-ui'
import type { EChartsOption } from 'echarts'
// 自定义主题
const customTheme = {
color: ['#1890ff', '#52c41a', '#faad14', '#f5222d', '#722ed1'],
backgroundColor: '#fff',
textStyle: {
color: '#333'
},
title: {
textStyle: {
color: '#333'
}
},
line: {
itemStyle: {
borderWidth: 2
},
lineStyle: {
width: 2
},
symbolSize: 6,
symbol: 'circle',
smooth: true
},
bar: {
itemStyle: {
barBorderWidth: 0,
barBorderColor: '#ccc'
}
}
}
const option: EChartsOption = {
// 图表配置...
}
</script>
<template>
<VbenChart
:option="option"
:theme="customTheme"
height="400px"
/>
</template>数据更新
vue
<script setup lang="ts">
import { ref } from 'vue'
import { VbenChart } from '@vben/common-ui'
import type { EChartsOption } from 'echarts'
const chartRef = ref()
const data = ref([150, 230, 224, 218, 135, 147, 260])
const option: EChartsOption = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: data.value,
type: 'line'
}
]
}
const updateData = () => {
// 更新数据
data.value = data.value.map(() => Math.floor(Math.random() * 300))
// 更新图表
chartRef.value?.setOption({
series: [{ data: data.value }]
})
}
</script>
<template>
<div>
<VbenChart ref="chartRef" :option="option" height="400px" />
<a-button @click="updateData">更新数据</a-button>
</div>
</template>注意事项
注意
- 图表组件需要指定高度才能正常显示
- 大数据量时注意性能优化
- 响应式图表需要监听窗口大小变化
- 销毁组件时会自动销毁图表实例
提示
- 使用
autoResize属性自动调整图表大小 - 可以通过
theme属性自定义主题 - 使用
loading属性显示加载动画 - 支持所有 ECharts 配置项和事件