echarts只需要修改其配置项即可

  1. <template>
  2. <MyPie :data="state.salePie"></MyPie>
  3. </template>
  4. <script setup lang='ts'>
  5. import { reactive } from 'vue';
  6. import {getAdminStat} from '../../request/api'
  7. import MyPie from './components/MyPie.vue'
  8. const state = reactive<{salePie:{}[]}>({
  9. salePie: []
  10. })
  11. getAdminStat().then(res => {
  12. if(res.errno === 0){
  13. state.salePie = res.data.salePie;
  14. }
  15. })
  16. </script>

因为要生成两种饼图,直接做成组件复用

  1. <template>
  2. <div id="pie" style="width: 100%;height:350px">
  3. </div>
  4. </template>
  5. <script setup lang='ts'>
  6. import { defineProps, onMounted, watch } from 'vue'
  7. import * as echarts from 'echarts'
  8. const props = defineProps<{
  9. data: {}[]
  10. }>()
  11. watch(() => props.data, () => {
  12. const arr = props.data.map(item => ({ value: item.today_money, name: item.name }))
  13. var myChart = echarts.init(document.getElementById('pie') as HTMLDivElement)
  14. var option = {
  15. tooltip: {
  16. trigger: 'item'
  17. },
  18. legend: {
  19. top: '5%',
  20. left: 'center'
  21. },
  22. series: [
  23. {
  24. name: 'Access From',
  25. type: 'pie',
  26. radius: ['40%', '70%'],
  27. avoidLabelOverlap: false,
  28. label: {
  29. show: false,
  30. position: 'center'
  31. },
  32. emphasis: {
  33. label: {
  34. show: true,
  35. fontSize: '40',
  36. fontWeight: 'bold'
  37. }
  38. },
  39. labelLine: {
  40. show: false
  41. },
  42. data: arr
  43. }
  44. ]
  45. };
  46. option && myChart.setOption(option);
  47. })
  48. </script>

因为数据是异步传入组件里的,因此还是采用watch去监听,然后再处理为饼图需要的数据类型,最后渲染处理。注意生命周期函数的时机
父子组件:
先父组件 beforeCreate Created beforeMount
然后是子组件的beforeCreate Created beforeMount Mounted
最后是父组件的Mounted

饼图配置项

  1. tooltip: {
  2. trigger: 'item'
  3. },

触发类型:鼠标经过子项时显示提示文字
image.png

  1. legend: {
  2. top: '5%',
  3. left: 'center'
  4. },

图例方位

  1. legend: {
  2. top: 20,
  3. right: 10,
  4. width: 300,
  5. height: 100,
  6. orient: 'vertical'
  7. },

image.png将图例放到右上角对齐

  1. series: [
  2. {
  3. name: 'Access From',
  4. type: 'pie',
  5. radius: ['40%', '70%'],
  6. center: ['30%','60%'],
  7. label: {
  8. show: true,
  9. },
  10. labelLine: {
  11. show: true
  12. },
  13. data: arr
  14. }
  15. ]

center决定主图位置坐标
label为子项标注,labelLine为引线(都默认开启)
image.png

确定真正要展示的数据

需要一个单选按钮和下拉多选框进行数据的筛选

当这些数据变化时,需要根据新的数据去生成饼图

  1. <template>
  2. <el-radio-group v-model="selectLabel" size="large" @change="dataChange">
  3. <el-radio-button label="sale_" >销量</el-radio-button>
  4. <el-radio-button label="_money" >销售额</el-radio-button>
  5. </el-radio-group>
  6. <el-select v-model="selectDay" placeholder="Select" @change="dataChange">
  7. <el-option
  8. v-for="item in options"
  9. :key="item.value"
  10. :label="item.name"
  11. :value="item.value"
  12. />
  13. </el-select>
  14. <div id="pie" style="width: 100%;height:350px">
  15. </div>
  16. </template>

这里可以用watch去监听,也可以使用element+本身就有的change事件

  1. <script setup lang='ts'>
  2. import { defineProps, onMounted, reactive, toRefs, watch } from 'vue'
  3. import * as echarts from 'echarts'
  4. const props = defineProps<{
  5. data: {}[]
  6. }>()
  7. const state = reactive({
  8. selectLabel: '_money',
  9. selectDay: 'today',
  10. options: [
  11. {name: '今天',value: 'today'},
  12. {name: '昨天',value: 'yesterday'},
  13. {name: '前三天',value: 'three_days'},
  14. {name: '前七天',value: 'seven_days'},
  15. ]
  16. })
  17. const {selectLabel,selectDay,options} = toRefs(state);
  18. const dataChange = () => {
  19. initPie();
  20. }
  21. const initPie = () => {
  22. let key ='';
  23. if(selectLabel.value === '_money'){
  24. key = selectDay.value + selectLabel.value
  25. }else{
  26. key = selectLabel.value + selectDay.value
  27. }
  28. const arr = props.data.map(item => ({ value: item[key], name: item.name }))
  29. var myChart = echarts.init(document.getElementById('pie') as HTMLDivElement)
  30. var option = {
  31. tooltip: {
  32. trigger: 'item'
  33. },
  34. legend: {
  35. top: 20,
  36. right: 10,
  37. width: 300,
  38. height: 100,
  39. orient: 'vertical'
  40. },
  41. series: [
  42. {
  43. name: 'Access From',
  44. type: 'pie',
  45. radius: ['40%', '70%'],
  46. center: ['30%','60%'],
  47. label: {
  48. show: true,
  49. },
  50. labelLine: {
  51. show: true
  52. },
  53. data: arr
  54. }
  55. ]
  56. };
  57. option && myChart.setOption(option);
  58. }
  59. //等有效数据传入之后再生成echarts
  60. watch(() => props.data, () => {
  61. initPie();
  62. })
  63. </script>

将生成图标封装为函数,在里面去收集两个框的内容并拼接,随后生成图表

系统提示:不需要重复生成echarts元素
因为在initPie中,我们总是会生成myChart

因此进行优化,可以在外部先设变量myChart,每次生成前进行判断
image.png
对map里的item也进行快速类型定义

地图

新建地图组件 MyMap.vue
引入echarts和地图数据

  1. import * as echarts from 'echarts';
  2. import china from '../../../data/china.json'
  3. echarts.registerMap('china',china as any);

需要先对数据进行处理,也是对象数组

  1. const props = defineProps<{ data: {}[] }>()
  2. let myChart: echarts.ECharts;
  3. watch(() => props.data, () => {
  4. const data = props.data.map((item: { [key: string]: string | number }) => ({ name: item.areaName, value: item.saleNum }))
  5. if (!myChart) {
  6. myChart = echarts.init(document.getElementById('map') as HTMLDivElement)
  7. }
  8. const options = {
  9. tooltip: {
  10. show: true,
  11. formatter: '{b0}<br/>销量: {c0}',
  12. backgroundColor: 'rgba(50,50,50,0.7)',
  13. textStyle: {
  14. color: '#fff'
  15. }
  16. },
  17. series: {
  18. type: 'map',
  19. map: 'china',
  20. emphasis: {
  21. label: {
  22. show: false
  23. },
  24. itemStyle: {
  25. areaColor: 'red'
  26. }
  27. },
  28. itemStyle: { borderColor: '#fff' },
  29. data
  30. },
  31. visualMap: {
  32. type: 'continuous',
  33. min: 0,
  34. max: 1000000,
  35. calculable: true,
  36. inRange:{
  37. color: ['#121122','rgba(3,4,5,0.4)','red']
  38. }
  39. }
  40. }
  41. options && myChart.setOption(options);
  42. })

配置理解

  1. series: {
  2. type: 'map',
  3. map: 'china',
  4. emphasis: {
  5. label: {
  6. show: false
  7. },
  8. itemStyle: {
  9. areaColor: 'red'
  10. }
  11. },
  12. itemStyle: { borderColor: '#fff' },
  13. data
  14. },

areaColor为鼠标经过地图区域时显示的颜色
itemStyle: { borderColor: ‘#fff’ },为边框颜色

图例

  1. tooltip: {
  2. show: true,
  3. formatter: '{b0}<br/>销量: {c0}',
  4. backgroundColor: 'rgba(50,50,50,0.7)',
  5. textStyle: {
  6. color: '#fff'
  7. }
  8. },

其中formatter可以格式化展示的内容
image.png
手柄渐变色

  1. visualMap: {
  2. type: 'continuous',
  3. min: 0,
  4. max: 1000000,
  5. calculable: true,
  6. inRange:{
  7. color: ['#121122','rgba(3,4,5,0.4)','red']
  8. }
  9. }

inRange的数组可以传递很多颜色,分别是数据由少变多的过程,这里red是深的