20vue3实战-----使用echarts搭建各种图表
20vue3实战-----使用echarts搭建各种图表
- 1.实现目标
- 2.实现步骤
- 2.1封装组件
- 2.2使用组件
1.实现目标
如上,页面上有各种各样类型的图标。这时候需要用到echarts库作为辅助。
2.实现步骤
首先安装echarts库的步骤就不用多说。
2.1封装组件
page-echarts/index.ts:
import BaseEchart from './src/base-echart.vue'
import PieEchart from './src/pie-echart.vue'
import LineEchart from './src/line-echart.vue'
import RoseEchart from './src/rose-echart.vue'
import BarEchart from './src/bar-echart.vue'
import MapEchart from './src/map-echart.vue'
export { PieEchart, LineEchart, RoseEchart, BarEchart, MapEchart }
export default BaseEchart
page-echarts/src/bar-echart.vue:
<template>
<div class="bar-echart">
<base-echart :option="option"></base-echart>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import * as echarts from 'echarts'
import BaseEchart from './base-echart.vue'
import type { EChartsOption } from 'echarts'
const props = defineProps<{
labels: string[]
values: string[]
}>()
const option = computed<EChartsOption>(() => {
return {
title: {
text: '支持鼠标滚动缩放'
},
grid: {
bottom: '5%'
},
xAxis: {
data: props.labels,
axisLabel: {
inside: true,
color: '#fff'
},
z: 10
},
yAxis: {
axisLabel: {
color: '#999'
}
},
dataZoom: [
{
type: 'inside'
}
],
series: [
{
type: 'bar',
showBackground: true,
// 系列图形的样式(每个item的样式)
// 可以被放到每一项中,针对每一项设置
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
])
},
// 图形的高亮: 鼠标悬浮时候的状态: hover
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#2378f7' },
{ offset: 0.7, color: '#2378f7' },
{ offset: 1, color: '#83bff6' }
])
}
},
data: props.values
}
]
}
})
</script>
<style scoped></style>
page-echarts/src/line-echart.vue:
<template>
<div class="line-echart">
<base-echart :option="option" />
</div>
</template>
<script setup lang="ts">
import { defineProps, computed } from 'vue'
import BaseEchart from './base-echart.vue'
import type { EChartsOption } from 'echarts'
const props = defineProps<{
labels: string[]
values: string[]
}>()
const option = computed<EChartsOption>(() => {
return {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: props.labels
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: '分类销量统计',
type: 'line',
stack: '总量',
areaStyle: {},
emphasis: {
focus: 'series'
},
data: props.values
}
]
}
})
</script>
<style lang="less" scoped></style>
page-echarts/src/map-echart.vue:
<template>
<div class="map-echart">
<base-echart :option="option"></base-echart>
</div>
</template>
<script setup lang="ts">
import { defineProps, computed } from 'vue'
import BaseEchart from './base-echart.vue'
import { convertData } from '../utils/convert-data'
import type { IEchartValueType } from '../types'
import type { EChartsOption } from 'echarts'
const props = defineProps<{
mapData: IEchartValueType[]
}>()
const option = computed<EChartsOption>(() => {
return {
backgroundColor: '#fff',
title: {
text: '全国销量统计',
left: 'center',
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: 'item',
formatter: function (params: any) {
return params.name + ' : ' + params.value[2]
}
},
visualMap: {
min: 0,
max: 60000,
left: 20,
bottom: 20,
calculable: true,
text: ['高', '低'],
inRange: {
color: ['rgb(70, 240, 252)', 'rgb(250, 220, 46)', 'rgb(245, 38, 186)']
},
textStyle: {
color: '#fff'
}
},
geo: {
// 设置使用的地图(注册过的china地址)
map: 'china',
// 漫步: 支持鼠标缩放效果
roam: 'scale',
emphasis: {
areaColor: '#f4cccc',
borderColor: 'rgb(9, 54, 95)',
itemStyle: {
areaColor: '#f4cccc'
}
}
},
series: [
{
name: '销量',
// 散点图在地图上展示数据
type: 'scatter',
coordinateSystem: 'geo',
data: convertData(props.mapData),
// 散点的大小(可以根据数据不同显示不同的大小, 设置为一个函数)
symbolSize: 12,
emphasis: {
itemStyle: {
borderColor: '#fff',
borderWidth: 1
}
}
},
{
// 会自动生成geo地理坐标系统
type: 'map',
// 设置使用的地图名称, 复用的是第0个坐标系统
map: 'china',
geoIndex: 0,
// 缩放地图
aspectScale: 0.75,
tooltip: {
show: false
}
}
]
}
})
</script>
<style scoped></style>
page-echarts/src/pie-echart.vue:
<template>
<div class="pie-echart">
<base-echart :option="option" />
</div>
</template>
<script setup lang="ts">
import BaseEchart from './base-echart.vue'
import type { EChartsOption } from 'echarts'
import { computed } from 'vue'
import type { IEchartValueType } from '../types'
interface IProps {
pieData: IEchartValueType[]
}
const props = defineProps<IProps>()
const option = computed<EChartsOption>(() => {
return {
// 手指放上去的时候显示的文本
tooltip: {
trigger: 'item'
},
// 图例:
legend: {
orient: 'horizontal',
left: 'left'
},
series: [
{
name: '访问来源',
type: 'pie',
radius: '50%',
bottom: '-10%',
data: props.pieData,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
})
</script>
<style lang="less" scoped>
.pie-echart {
color: red;
}
</style>
page-echarts/src/rose-echart.vue:
<template>
<div class="rose-echart">
<base-echart :option="option" />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import BaseEchart from './base-echart.vue'
import type { EChartsOption } from 'echarts'
import type { IEchartValueType } from '../types'
interface IProps {
roseData: IEchartValueType[]
}
const props = defineProps<IProps>()
const option = computed<EChartsOption>(() => {
return {
toolbox: {
show: true,
feature: {
mark: { show: true },
dataView: { show: true, readOnly: false },
restore: { show: true },
saveAsImage: { show: true }
}
},
tooltip: {
trigger: 'item'
},
series: [
{
name: '访问来源',
type: 'pie',
// 内半径/外半径的大小
radius: [10, 160],
// 设置区域的位置
center: ['50%', '50%'],
bottom: '-15%',
roseType: 'area', // 圆心角一样, 通过半径的不同表示大小
itemStyle: {
borderRadius: 8
},
data: props.roseData,
label: {
show: false
}
}
]
}
})
</script>
<style lang="less" scoped>
.rose-echart {
color: red;
}
</style>
page-echarts/src/base-echart.vue:
<template>
<div class="base-echart">
<div class="echart" ref="echartRef"></div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, watchEffect } from 'vue'
import * as echarts from 'echarts'
import type { EChartsOption } from 'echarts'
import ChinaJSON from '../data/china.json'
echarts.registerMap('china', ChinaJSON as any)
interface IProps {
option: EChartsOption
}
const props = defineProps<IProps>()
const echartRef = ref<HTMLElement>()
onMounted(() => {
// 1.初始化echarts实例
const echartInstance = echarts.init(echartRef.value!, 'light', {
renderer: 'canvas'
})
// 2.第一次进行setOption
// watchEffect监听option变化, 重新执行
watchEffect(() => echartInstance.setOption(props.option))
// 3.监听window缩放
window.addEventListener('resize', () => {
echartInstance.resize()
})
})
onMounted(() => {})
</script>
<style lang="less" scoped>
.base-echart {
color: red;
}
.echart {
height: 300px;
}
</style>
2.2使用组件
<template>
<div class="dashboard">
<!-- 1.顶部数字的数据展示 -->
<el-row :gutter="10">
<template v-for="item in amountList" :key="item.amount">
<el-col :span="6" :xs="24" :sm="12" :md="8" :lg="6">
<count-card v-bind="item" />
</el-col>
</template>
</el-row>
<!-- 2.中间部分的图表 -->
<el-row :gutter="10">
<el-col :span="7">
<chart-card>
<pie-echart :pie-data="showGoodsCategoryCount" />
</chart-card>
</el-col>
<el-col :span="10">
<chart-card>
<map-echart :map-data="showGoodsAddressSale" />
</chart-card>
</el-col>
<el-col :span="7">
<chart-card>
<rose-echart :rose-data="showGoodsCategoryCount" />
</chart-card>
</el-col>
</el-row>
<!-- 3.底部部分的图表 -->
<el-row :gutter="10">
<el-col :span="12">
<chart-card>
<line-echart v-bind="showGoodsCategorySale" />
</chart-card>
</el-col>
<el-col :span="12">
<chart-card>
<bar-echart v-bind="showGoodsCategoryFavor" />
</chart-card>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { storeToRefs } from 'pinia'
import CountCard from './c-cpns/count-card/count-card.vue'
import ChartCard from './c-cpns/chart-card/chart-card.vue'
import useAnalysisStore from '@/store/main/analysis/analysis'
// import BaseChart from '@/components/page-echarts'
import {
PieEchart,
LineEchart,
RoseEchart,
BarEchart,
MapEchart
} from '@/components/page-echarts'
// 1.发起数据的请求
const analysisStore = useAnalysisStore()
analysisStore.fetchAnalysisDataAction()
// 2.从store获取数据
const {
amountList,
goodsCategoryCount,
goodsCategorySale,
goodsCategoryFavor,
goodsAddressSale
} = storeToRefs(analysisStore)
// 3.获取数据
const showGoodsCategoryCount = computed(() => {
return goodsCategoryCount.value.map((item) => ({
name: item.name,
value: item.goodsCount
}))
})
const showGoodsCategorySale = computed(() => {
const labels = goodsCategorySale.value.map((item) => item.name)
const values = goodsCategorySale.value.map((item) => item.goodsCount)
return { labels, values }
})
const showGoodsCategoryFavor = computed(() => {
const labels = goodsCategoryFavor.value.map((item) => item.name)
const values = goodsCategoryFavor.value.map((item) => item.goodsFavor)
return { labels, values }
})
const showGoodsAddressSale = computed(() => {
return goodsAddressSale.value.map((item) => ({
name: item.address,
value: item.count
}))
})
</script>
<style lang="less" scoped>
...
</style>