目录

一、安装 Echarts

二、Echarts 自适应大小工具类

三、使用案例


一、安装 Echarts

npm install echarts

二、Echarts适应大小工具

src/utils新建resize.ts

import { ref } from 'vue';
export default function () {
  const chart = ref<any>();
  const sidebarElm = ref<Element>();

  const chartResizeHandler = () => {
    if (chart.value) {
      chart.value.resize();
    }
  };

  const sidebarResizeHandler = (e: TransitionEvent) => {
    if (e.propertyName === 'width') {
      chartResizeHandler();
    }
  };

  const initResizeEvent = () => {
    window.addEventListener('resize', chartResizeHandler, {passive:true});
  };

  const destroyResizeEvent = () => {
    window.removeEventListener('resize', chartResizeHandler);
  };

  const initSidebarResizeEvent = () => {
    sidebarElm.value = document.getElementsByClassName('sidebar-container')[0];
    if (sidebarElm.value) {
      sidebarElm.value.addEventListener(
        'transitionend',
        sidebarResizeHandler as EventListener,
        {passive:true}
      );
    }
  };

  const destroySidebarResizeEvent = () => {
    if (sidebarElm.value) {
      sidebarElm.value.removeEventListener(
        'transitionend',
        sidebarResizeHandler as EventListener
      );
    }
  };

  const mounted = () => {
    initResizeEvent();
    initSidebarResizeEvent();
  };

  const beforeDestroy = () => {
    destroyResizeEvent();
    destroySidebarResizeEvent();
  };

  const activated = () => {
    initResizeEvent();
    initSidebarResizeEvent();
  };

  const deactivated = () => {
    destroyResizeEvent();
    destroySidebarResizeEvent();
  };

  return {
    chart,
    mounted,
    beforeDestroy,
    activated,
    deactivated
  };
}

三、使用案例

views下新建dashboard文件夹,在dashboard文件夹新建components文件夹,在components新建Chart文件夹,在Chart文件夹新建BarChart.vue、FunnelChart.vue、PieChart.vue、RadarChart.vue

<!--src/views/dashboard/components/Chart/BarChart.vue-->
<!--  线 + 柱混合图 -->
<template>
  <div :id="id" :class="className" :style="{ height, width }" />
</template>

<script setup lang="ts">
import {
  nextTick,
  onActivated,
  onBeforeUnmount,
  onDeactivated,
  onMounted,
} from 'vue';
import { init, EChartsOption } from 'echarts';
import * as echarts from 'echarts';
import resize from '@/utils/resize';

const props = defineProps({
  id: {
    type: String,
    default: 'barChart',
  },
  className: {
    type: String,
    default: '',
  },
  width: {
    type: String,
    default: '200px',
    required: true,
  },
  height: {
    type: String,
    default: '200px',
    required: true,
  },
});

const { mounted, chart, beforeDestroy, activated, deactivated } = resize();

function initChart() {
  const barChart = init(document.getElementById(props.id) as HTMLDivElement);

  barChart.setOption({
    title: {
      show: true,
      text: '业绩总览',
      x: 'center',
      padding: 15,
      textStyle: {
        fontSize: 18,
        fontStyle: 'normal',
        fontWeight: 'bold',
        color: '#337ecc',
      },
    },
    grid: {
      left: '2%',
      right: '2%',
      bottom: '10%',
      containLabel: true,
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross',
        crossStyle: {
          color: '#999',
        },
      },
    },
    legend: {
      x: 'center',
      y: 'bottom',
      data: ['收入', '毛利润', '收入增长率', '利润增长率'],
    },
    xAxis: [
      {
        type: 'category',
        data: [ '浙江', '北京', '上海', '广东','深圳'],
        axisPointer: {
          type: 'shadow',
        },
      },
    ],
    yAxis: [
      {
        type: 'value',
        min: 0,
        max: 10000,
        interval: 2000,
        axisLabel: {
          formatter: '{value} ',
        },
      },
      {
        type: 'value',
        min: 0,
        max: 100,
        interval: 20,
        axisLabel: {
          formatter: '{value}%',
        },
      },
    ],
    series: [
      {
        name: '收入',
        type: 'bar',
        data: [7000, 7100, 7200, 7300,7400],
        barWidth: 20,
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: '#83bff6' },
            { offset: 0.5, color: '#188df0' },
            { offset: 1, color: '#188df0' },
          ]),
        },
      },
      {
        name: '毛利润',
        type: 'bar',
        data: [ 8000,8200, 8400, 8600, 8800],
        barWidth: 20,
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: '#25d73c' },
            { offset: 0.5, color: '#1bc23d' },
            { offset: 1, color: '#179e61' },
          ]),
        },
      },
      {
        name: '收入增长率',
        type: 'line',
        yAxisIndex: 1,
        data: [  60,65, 70, 75, 80],
        itemStyle: {
          color: '#67C23A',
        },
      },
      {
        name: '利润增长率',
        type: 'line',
        yAxisIndex: 1,
        data: [  70,75, 80, 85, 90],
        itemStyle: {
          color: '#409EFF',
        },
      },
    ],
  } as EChartsOption);
  chart.value = barChart;
}

onBeforeUnmount(() => {
  beforeDestroy();
});

onActivated(() => {
  activated();
});

onDeactivated(() => {
  deactivated();
});

onMounted(() => {
  mounted();
  nextTick(() => {
    initChart();
  });
});
</script>
<!--src/views/dashboard/components/Chart/FunnelChart.vue-->
<!-- 漏斗图 -->
<template>
  <div :id="id" :class="className" :style="{ height, width }" />
</template>

<script setup lang="ts">
import {
  nextTick,
  onActivated,
  onBeforeUnmount,
  onDeactivated,
  onMounted
} from 'vue';
import { init, EChartsOption } from 'echarts';
import resize from '@/utils/resize';

const props = defineProps({
  id: {
    type: String,
    default: 'funnelChart'
  },
  className: {
    type: String,
    default: ''
  },
  width: {
    type: String,
    default: '200px',
    required: true
  },
  height: {
    type: String,
    default: '200px',
    required: true
  }
});

const { mounted, chart, beforeDestroy, activated, deactivated } = resize();

function initChart() {
  const funnelChart = init(document.getElementById(props.id) as HTMLDivElement);

  funnelChart.setOption({
    title: {
      show: true,
      text: '订单线索转化漏斗图',
      x: 'center',
      padding: 15,
      textStyle: {
        fontSize: 18,
        fontStyle: 'normal',
        fontWeight: 'bold',
        color: '#337ecc'
      }
    },
    grid: {
      left: '2%',
      right: '2%',
      bottom: '10%',
      containLabel: true
    },
    legend: {
      x: 'center',
      y: 'bottom',
      data: ['Show', 'Click', 'Visit', 'Inquiry', 'Order']
    },

    series: [
      {
        name: 'Funnel',
        type: 'funnel',
        left: '20%',
        top: 60,
        bottom: 60,
        width: '60%',
        sort: 'descending',
        gap: 2,
        label: {
          show: true,
          position: 'inside'
        },
        labelLine: {
          length: 10,
          lineStyle: {
            width: 1,
            type: 'solid'
          }
        },
        itemStyle: {
          borderColor: '#fff',
          borderWidth: 1
        },
        emphasis: {
          label: {
            fontSize: 20
          }
        },
        data: [
          { value: 60, name: 'Visit' },
          { value: 40, name: 'Inquiry' },
          { value: 20, name: 'Order' },
          { value: 80, name: 'Click' },
          { value: 100, name: 'Show' }
        ]
      }
    ]
  } as EChartsOption);
  chart.value = funnelChart;
}

onBeforeUnmount(() => {
  beforeDestroy();
});

onActivated(() => {
  activated();
});

onDeactivated(() => {
  deactivated();
});

onMounted(() => {
  mounted();
  nextTick(() => {
    initChart();
  });
});
</script>

<style lang="scss" scoped></style>
<!--src/views/dashboard/components/Chart/PieChart.vue-->
<!-- 饼图 -->
<template>
  <div :id="id" :class="className" :style="{ height, width }" />
</template>

<script setup lang="ts">
import {
  nextTick,
  onActivated,
  onBeforeUnmount,
  onDeactivated,
  onMounted
} from 'vue';
import { init, EChartsOption } from 'echarts';
import resize from '@/utils/resize';

const props = defineProps({
  id: {
    type: String,
    default: 'pieChart'
  },
  className: {
    type: String,
    default: ''
  },
  width: {
    type: String,
    default: '200px',
    required: true
  },
  height: {
    type: String,
    default: '200px',
    required: true
  }
});

const { mounted, chart, beforeDestroy, activated, deactivated } = resize();

function initChart() {
  const pieChart = init(document.getElementById(props.id) as HTMLDivElement);

  pieChart.setOption({
    title: {
      show: true,
      text: '产品分类总览',
      x: 'center',
      padding: 15,
      textStyle: {
        fontSize: 18,
        fontStyle: 'normal',
        fontWeight: 'bold',
        color: '#337ecc'
      }
    },
    grid: {
      left: '2%',
      right: '2%',
      bottom: '10%',
      containLabel: true
    },
    legend: {
      top: 'bottom'
    },
    series: [
      {
        name: 'Nightingale Chart',
        type: 'pie',
        radius: [50, 130],
        center: ['50%', '50%'],
        roseType: 'area',
        itemStyle: {
          borderRadius: 1,
          color: function (params: any) {
            //自定义颜色
            const colorList = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'];
            return colorList[params.dataIndex];
          }
        },
        data: [
          { value: 26, name: '家用电器' },
          { value: 27, name: '户外运动' },
          { value: 24, name: '汽车用品' },
          { value: 23, name: '手机数码' }
        ]
      }
    ]
  } as EChartsOption);

  chart.value = pieChart;
}

onBeforeUnmount(() => {
  beforeDestroy();
});

onActivated(() => {
  activated();
});

onDeactivated(() => {
  deactivated();
});

onMounted(() => {
  mounted();
  nextTick(() => {
    initChart();
  });
});
</script>

<style lang="scss" scoped></style>
<!--src/views/dashboard/components/Chart/RadarChart.vue-->
<!-- 雷达图 -->
<template>
  <div :id="id" :class="className" :style="{ height, width }" />
</template>

<script setup lang="ts">
import {
  nextTick,
  onActivated,
  onBeforeUnmount,
  onDeactivated,
  onMounted
} from 'vue';
import { init, EChartsOption } from 'echarts';
import resize from '@/utils/resize';

const props = defineProps({
  id: {
    type: String,
    default: 'radarChart'
  },
  className: {
    type: String,
    default: ''
  },
  width: {
    type: String,
    default: '200px',
    required: true
  },
  height: {
    type: String,
    default: '200px',
    required: true
  }
});

const { mounted, chart, beforeDestroy, activated, deactivated } = resize();

function initChart() {
  const radarChart = init(document.getElementById(props.id) as HTMLDivElement);

  radarChart.setOption({
    title: {
      show: true,
      text: '订单状态统计',
      x: 'center',
      padding: 15,
      textStyle: {
        fontSize: 18,
        fontStyle: 'normal',
        fontWeight: 'bold',
        color: '#337ecc'
      }
    },
    grid: {
      left: '2%',
      right: '2%',
      bottom: '10%',
      containLabel: true
    },
    legend: {
      x: 'center',
      y: 'bottom',
      data: ['预定数量', '下单数量', '发货数量']
    },
    radar: {
      // shape: 'circle',
      radius: '60%',
      indicator: [
        { name: '家用电器' },
        { name: '服装箱包' },
        { name: '运动户外' },
        { name: '手机数码' },
        { name: '汽车用品' },
        { name: '家具厨具' }
      ]
    },
    series: [
      {
        name: 'Budget vs spending',
        type: 'radar',
        itemStyle: {
          borderRadius: 6,
          color: function (params: any) {
            //自定义颜色
            const colorList = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'];
            return colorList[params.dataIndex];
          }
        },
        data: [
          {
            value: [400, 400, 400, 400, 400, 400],
            name: '预定数量'
          },
          {
            value: [300, 300, 300, 300, 300, 300],
            name: '下单数量'
          },
          {
            value: [200, 200, 200, 200, 200, 200],
            name: '发货数量'
          }
        ]
      }
    ]
  } as EChartsOption);

  chart.value = radarChart;
}

onBeforeUnmount(() => {
  beforeDestroy();
});

onActivated(() => {
  activated();
});

onDeactivated(() => {
  deactivated();
});

onMounted(() => {
  mounted();
  nextTick(() => {
    initChart();
  });
});
</script>

<style lang="scss" scoped></style>

使用组件

<!--src/App.vue-->
<script lang="ts">
export default {name: 'Dashboard'};
</script>

<script setup lang="ts">
// 组件引用
import BarChart from '@/views/dashboard/components/Chart/BarChart.vue';
import PieChart from '@/views/dashboard/components/Chart/PieChart.vue';
import RadarChart from '@/views/dashboard/components/Chart/RadarChart.vue';

</script>

<template>
  <div>
    <el-row>
      <el-col :span="8">
        <BarChart id="barChart" height="400px" width="400px"/>
      </el-col>
      <el-col :span="8">
        <PieChart id="pieChart" height="400px" width="400px"/>
      </el-col>
      <el-col :span="8">
        <RadarChart id="radarChart" height="400px" width="400px"/>
      </el-col>
    </el-row>
    
  </div>
</template>

<style lang="scss" scoped>

</style>

原文地址:https://blog.csdn.net/wenxingchen/article/details/129178398

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_8755.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注