本文我简单讲解分享一下vue实现可视化图表前端的核心逻辑,看完本篇使用 vue3 + echarts 手搓几个针对数据渲染的图表不在话下

在企业级数据管理场景中,可视化图表是呈现业务数据的核心载体。本文将基于 Vue3 和 ECharts,实现一个包含柱状图、饼状图等;读取接口的数据渲染出图表格,这里为了照顾前端的朋友,直接给出接口请求到的数据格式,可以参考我的数据制作mock数据! 

[
    {
        "日销单明细ID": "RXDMX-04dd397d319628747d4be54ab4aefbad-3",
        "日销单ID": "RXD-SLFS01452-1534299369-1",
        "款式组合编码": "SL-D03-X02-D1-TS-70-7006",
        "销售数量": "17",
        "零售单价": "75.0",
        "折扣率": "0.27",
        "折后单价": "54.75",
        "折后总价": "930.75",
        "门店编码": "SLFS01452",
        "导购员编码": "SL6624111",
        "交易时间": "2024-08-15 10:16:09",
        "款式组合名称": "中档-短袖T恤D1-70(L)-米灰色",
        "款式编码": "SL-D03-X02-D1",
        "导购员姓名": "仵朝阳",
        "是否门店经理": "1",
        "门店名称": "盛利服饰(向阳路店)"
    },
    {
        "日销单明细ID": "RXDMX-439caa8c685ec12ada4c7c8d3e097ee6-5",
        "日销单ID": "RXD-SLFS01211-1505042108-1",
        "款式组合编码": "SL-D05-X01-C5-TY-M-9022",
        "销售数量": "20",
        "零售单价": "130.0",
        "折扣率": "0.34",
        "折后单价": "85.8",
        "折后总价": "1716.0",
        "门店编码": "SLFS01211",
        "导购员编码": "SL5221332",
        "交易时间": "2023-09-10 19:15:08",
        "款式组合名称": "低档-光皮皮衣C5-M-珍珠浅灰",
        "款式编码": "SL-D05-X01-C5",
        "导购员姓名": "曹智超",
        "是否门店经理": "0",
        "门店名称": "盛利服饰(银信广场店)"
    },
]

很好接下来就是代码部分,清晰可见,当然这里echats 是下载在本地了, 读者看到可以使用script直接引入到组件或者下载,参考 快速上手 - 使用手册 - Apache ECharts

 app.vue 

<template>
  <!-- <HelloWorld msg="Welcome to Your Vue.js App"/> -->
  <!-- <TopTenSellman/> --> <br><br>
  <!-- <LowNumShop/> --> <br><br>
  <LineMonthSell/> <br><br>
  <PieMonthShop/> <br><br>
  <RoseTenShop/> <br><br>
</template>

<script setup>
// import HelloWorld from './components/HelloWorld.vue'
import TopTenSellman from './components/TopTenSellman.vue'
import LowNumShop from './components/LowNumShop.vue'
import LineMonthSell from './components/LineMonthSell.vue'
import PieMonthShop from './components/PieMonthShop.vue'
import RoseTenShop from './components/RoseTenShop.vue'


</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

前10排名的柱形图

topTenSellMan.vue 组件

<template>
  <div ref="chartRef" class="chart-container"></div>
</template>

<script setup>
// todo 用柱状图展示2024年销售金额最高的前10个导购
import { ref, onMounted } from 'vue'
import * as echarts from '../assets/echarts.js'
import clothingSalesData from '../data/clothing_sales_data.json'

const processData = (data) => {
  // 按照 x轴的数据 分组
  const groupData = {}

  data.forEach(el => {
    const sellman = el.导购员姓名
    // 保留两位小数
    // 四舍五入这个数值
    const sellAmount = Number(el.折后单价)
    const year = new Date(el.交易时间).getFullYear()
    // console.log('sellman ',sellman,';  sellAmount ',sellAmount ,';  year ',year);

    if (year === 2024) {
      /* toFixed(2) 将数字格式化为保留2位小数的字符串
         parseFloat() 将字符串转回数字,这样可以继续进行数学运算 */
      groupData[sellman] = parseFloat((groupData[sellman] || 0) + sellAmount).toFixed(2)
    }
  })

  // 排序取前n位
  const finalData = Object.entries(groupData)
    .map(([sellman, sellAmount]) => ({
      sellman,
      sellAmount
    }))
    .sort((a, b) => b.sellAmount - b.sellAmount)
    .slice(0, 10)

  // console.log('finalData', finalData)
  return finalData
}

// todo 绘制 echarts 图表
const chartRef = ref()

const initChart = (data) => {
  const myChart = echarts.init(chartRef.value)

  const sellman = data.map(el => el.sellman)
  const sellAmount = data.map(el => el.sellAmount)

  const option = {
    title: {
      text: '一、用柱状图展示2024年销售金额最高的前10个导购',
      left: 'center'
    },
    xAxis: {
      type: 'category',
      data: sellman,
      axisLabel:{
        rotate:26,
      }
    },
    yAxis: {
      type: 'value',
      name: '销售金额(元)'
    },
    tooltip: {
      trigger: 'axis', // 触发类型
      axisPointer: {
        type: 'shadow', // 鼠标悬停时显示阴影        
      }
    },
    series: [{
      name: '销售金额',
      type: 'bar',
      data: sellAmount,
      label: {
        show: true,
        position: 'top'
      }
    }]
  }

  myChart.setOption(option)
}


onMounted(() => {
  const chartdata = processData(clothingSalesData)
  console.log('chartdata', chartdata)
  initChart(chartdata)
})

</script>

<style scoped>
.chart-container {
  width: 700px;
  height: 400px;
  background-color: #f1f6ff;
  /* 浅蓝灰色背景,柔和不抢眼 */
  box-shadow: 0 0 8px 1px #748ede66;
  /* 使用主色调的透明阴影 */
  border-radius: 10px;
  margin-left: 50px;
}
</style>

柱形图2

<template>
  <div ref="chartRef" class="chart-container"></div>
</template>

<script setup>
// todo 子任务三:折线图展示 2023 年不同月份销售量变化
import { ref, onMounted } from 'vue'
import * as echarts from '../assets/echarts.js'
import clothingSalesData from '../data/clothing_sales_data.json'

const processData = (data) => {
  // 按照 x轴的数据 分组
  const groupData = {}

  data.forEach(el => {
    const sellAmount = Number(el.折后单价)
    const month = new Date(el.交易时间).getMonth()
    const year = new Date(el.交易时间).getFullYear()

    if (year === 2023) {
      /* toFixed(2) 将数字格式化为保留2位小数的字符串
         parseFloat() 将字符串转回数字,这样可以继续进行数学运算 */
      groupData[month] = parseFloat((groupData[month] || 0) + sellAmount).toFixed(2)
    }
  })

  // 排序取前n位
  const finalData = Object.entries(groupData)
    .map(([sellman, sellAmount]) => ({
      sellman,
      sellAmount
    }))
    .sort((a, b) => b.sellAmount - b.sellAmount)
    .slice(0, 10)

  // console.log('finalData', finalData)
  return finalData
}

// todo 绘制 echarts 图表
const chartRef = ref()

const initChart = (data) => {
  const myChart = echarts.init(chartRef.value)

  const sellman = data.map(el => el.sellman)
  const sellAmount = data.map(el => el.sellAmount)

  const option = {
    title: {
      text: '子任务三:折线图展示 2023 年不同月份销售量变化',
      left: 'center'
    },
    xAxis: {
      type: 'category',
      data: sellman,
      // axisLabel:{
      //   rotate:26,
      // }
    },
    yAxis: {
      type: 'value',
      name: '销售金额(元)'
    },
    tooltip: {
      trigger: 'axis', // 触发类型
      axisPointer: {
        type: 'shadow', // 鼠标悬停时显示阴影        
      }
    },
    series: [{
      name: '销售金额',
      type: 'line',
      smooth: true,
      // 线下面渐变颜色
      areaStyle: {
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          { offset: 0, color: '#748ede51' },
          { offset: 1, color: '#748ede01' }
        ]),
      },
      data: sellAmount,
      label: {
        show: true,
        position: 'top'
      }
    }]
  }

  myChart.setOption(option)
}


onMounted(() => {
  const chartdata = processData(clothingSalesData)
  console.log('chartdata', chartdata)
  initChart(chartdata)
})

</script>

<style scoped>
.chart-container {
  width: 700px;
  height: 400px;
  background-color: #f1f6ff;
  /* 浅蓝灰色背景,柔和不抢眼 */
  box-shadow: 0 0 8px 1px #748ede66;
  /* 使用主色调的透明阴影 */
  border-radius: 10px;
  margin-left: 50px;
}
</style>

图像渲染效果呈现

折线图 LineMonthSell.vue

<template>
  <div ref="chartRef" class="chart-container"></div>
</template>

<script setup>
// todo 子任务三:折线图展示 2023 年不同月份销售量变化
import { ref, onMounted } from 'vue'
import * as echarts from '../assets/echarts.js'
import clothingSalesData from '../data/clothing_sales_data.json'

const processData = (data) => {
  // 按照 x轴的数据 分组
  const groupData = {}

  data.forEach(el => {
    const sellAmount = Number(el.折后单价)
    const month = new Date(el.交易时间).getMonth()
    const year = new Date(el.交易时间).getFullYear()

    if (year === 2023) {
      /* toFixed(2) 将数字格式化为保留2位小数的字符串
         parseFloat() 将字符串转回数字,这样可以继续进行数学运算 */
      groupData[month] = parseFloat((groupData[month] || 0) + sellAmount).toFixed(2)
    }
  })

  // 排序取前n位
  const finalData = Object.entries(groupData)
    .map(([sellman, sellAmount]) => ({
      sellman,
      sellAmount
    }))
    .sort((a, b) => b.sellAmount - b.sellAmount)
    .slice(0, 10)

  // console.log('finalData', finalData)
  return finalData
}

// todo 绘制 echarts 图表
const chartRef = ref()

const initChart = (data) => {
  const myChart = echarts.init(chartRef.value)

  const sellman = data.map(el => el.sellman)
  const sellAmount = data.map(el => el.sellAmount)

  const option = {
    title: {
      text: '子任务三:折线图展示 2023 年不同月份销售量变化',
      left: 'center'
    },
    xAxis: {
      type: 'category',
      data: sellman,
      // axisLabel:{
      //   rotate:26,
      // }
    },
    yAxis: {
      type: 'value',
      name: '销售金额(元)'
    },
    tooltip: {
      trigger: 'axis', // 触发类型
      axisPointer: {
        type: 'shadow', // 鼠标悬停时显示阴影        
      }
    },
    series: [{
      name: '销售金额',
      type: 'line',
      smooth: true,
      // 线下面渐变颜色
      areaStyle: {
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          { offset: 0, color: '#748ede51' },
          { offset: 1, color: '#748ede01' }
        ]),
      },
      data: sellAmount,
      label: {
        show: true,
        position: 'top'
      }
    }]
  }

  myChart.setOption(option)
}


onMounted(() => {
  const chartdata = processData(clothingSalesData)
  console.log('chartdata', chartdata)
  initChart(chartdata)
})

</script>

<style scoped>
.chart-container {
  width: 700px;
  height: 400px;
  background-color: #f1f6ff;
  /* 浅蓝灰色背景,柔和不抢眼 */
  box-shadow: 0 0 8px 1px #748ede66;
  /* 使用主色调的透明阴影 */
  border-radius: 10px;
  margin-left: 50px;
}
</style>

饼状图

<template>
  <div ref="chartRef" class="chart-container"></div>
</template>

<script setup>
// todo 饼状图展示2023-2024 年不同门店的销售金额
import { ref, onMounted } from 'vue'
import * as echarts from '../assets/echarts.js'
import clothingSalesData from '../data/clothing_sales_data.json'

const processData = (data) => {
  // 按照 x轴的数据 分组
  const groupData = {}

  data.forEach(el => {
    const shopName = el.门店名称
    const sellAmount = Number(el.折后单价)
    const year = new Date(el.交易时间).getFullYear()

    if (year >= 2023 && year <= 2024) {
      /* toFixed(2) 将数字格式化为保留2位小数的字符串
         parseFloat() 将字符串转回数字,这样可以继续进行数学运算 */
      groupData[shopName] = parseFloat((groupData[shopName] || 0) + sellAmount).toFixed(2)
    }
  })

  // 排序取前n位
  const finalData = Object.entries(groupData)
    .map(([shopName, sellAmount]) => ({
      name:shopName,
      value:sellAmount
    }))
    .sort((a, b) => b.value - b.value)
    .slice(0, 10)

  // console.log('finalData', finalData)
  return finalData
}

// todo 绘制 echarts 图表
const chartRef = ref()

const initChart = (processData) => {
  const myChart = echarts.init(chartRef.value)


  const option = {
    title: {
      text: '任务四、饼状图展示 2023-2024 年不同门店的销售金额',
      left: 'center'
    },
    legend: {
      orient: 'vertical',
      left: 'left',
      top: 'middle'
    },
    tooltip: {
      trigger: 'item',
      formatter: '{a} <br/>{b} : {c} 元 ({d}%)'
    },
    series: [{
      name: '销售数量',
      type: 'pie',
      data: processData,
      radius: '50%',
      // roseType: 'radius',
      label: {
        show: true,
        formatter: ' {c} 元'
      }
    }]
  }

  myChart.setOption(option)
}


onMounted(() => {
  const chartdata = processData(clothingSalesData)
  console.log('chartdata', chartdata)
  initChart(chartdata)
})

</script>

<style scoped>
.chart-container {
  width: 700px;
  height: 400px;
  background-color: #f1f6ff;
  /* 浅蓝灰色背景,柔和不抢眼 */
  box-shadow: 0 0 8px 1px #748ede66;
  /* 使用主色调的透明阴影 */
  border-radius: 10px;
  margin-left: 50px;
}
</style>

Logo

永洪科技,致力于打造全球领先的数据技术厂商,具备从数据应用方案咨询、BI、AIGC智能分析、数字孪生、数据资产、数据治理、数据实施的端到端大数据价值服务能力。

更多推荐