在 UniApp 微信小程序中使用 uCharts 图表组件(Vue3版)

3,805 阅读5分钟

uCharts 是一款基于 Canvas 的高性能跨平台图表库,特别适合在 UniApp 中使用。本文将详细介绍如何在 UniApp 微信小程序项目中集成和使用 uCharts 图表组件。

二、安装与配置

1. 安装 uCharts

首先通过 npm 安装 uCharts:

npm install @qiun/ucharts

或者使用 yarn:

yarn add  @qiun/ucharts

三、基本使用示例

1. 基本柱状图示例

<template>
  <view class="container">
    <canvas
      canvasId="columnChart"
      type="column"
      :opts="columnOpts"
      :chartData="columnData"
      canvas2d
      @complete="onChartComplete"
    />
  </view>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import uCharts from '@qiun/ucharts'

// 图表数据
const columnData = ref({})
const columnOpts = ref({
  color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE"],
  padding: [15, 15, 0, 15],
  enableScroll: false,
  legend: {},
  xAxis: {
    disableGrid: true
  },
  yAxis: {
    gridType: "dash",
    dashLength: 2
  },
  extra: {
    column: {
      type: "group",
      width: 30
    }
  }
})

// 图表实例引用
const chartInstance = ref(null)

// 模拟获取数据
const fetchData = () => {
  // 这里通常是API请求,我们使用setTimeout模拟
  setTimeout(() => {
    columnData.value = {
      categories: ["2016", "2017", "2018", "2019", "2020", "2021"],
      series: [
        {
          name: "成交量A",
          data: [35, 36, 31, 33, 13, 34]
        },
        {
          name: "成交量B",
          data: [18, 27, 21, 24, 6, 28]
        }
      ]
    }
  }, 500)
}

// 图表渲染完成回调
const onChartComplete = (e) => {
  console.log('图表渲染完成', e)
  chartInstance.value = e.detail.instance
}

// 动态更新图表数据
const updateChartData = () => {
  const newData = {
    categories: ["Q1", "Q2", "Q3", "Q4"],
    series: [
      {
        name: "新数据A",
        data: [Math.random() * 50, Math.random() * 50, Math.random() * 50, Math.random() * 50]
      },
      {
        name: "新数据B",
        data: [Math.random() * 50, Math.random() * 50, Math.random() * 50, Math.random() * 50]
      }
    ]
  }
  columnData.value = newData
}

// 生命周期钩子
onMounted(() => {
  fetchData()
})
</script>

<style>
.container {
  width: 100%;
  height: 500rpx;
  padding: 20rpx;
  box-sizing: border-box;
}
</style>

2. 多图表示例(折线图+饼图)

<template>
  <view class="charts-container">
    <!-- 折线图 -->
    <view class="chart-wrapper">
      <canvas
        canvasId="lineChart"
        type="line"
        :opts="lineOpts"
        :chartData="lineData"
        canvas2d
      />
    </view>
    
    <!-- 饼图 -->
    <view class="chart-wrapper">
      <canvas
        canvasId="pieChart"
        type="pie"
        :opts="pieOpts"
        :chartData="pieData"
        canvas2d
      />
    </view>
    
    <button @click="updateAllCharts" type="primary">更新所有图表数据</button>
  </view>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import uCharts from '@qiun/ucharts'

// 折线图数据
const lineData = ref({})
const lineOpts = ref({
  color: ["#1890FF", "#91CB74"],
  padding: [15, 15, 0, 15],
  legend: {},
  xAxis: {
    disableGrid: true
  },
  yAxis: {
    gridType: "dash",
    dashLength: 2
  }
})

// 饼图数据
const pieData = ref({})
const pieOpts = ref({
  color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666"],
  padding: [5, 5, 5, 5],
  extra: {
    pie: {
      labelWidth: 15
    }
  }
})

// 初始化数据
const initData = () => {
  // 折线图数据
  lineData.value = {
    categories: ["1月", "2月", "3月", "4月", "5月", "6月"],
    series: [
      {
        name: "销售额",
        data: [35, 20, 25, 37, 4, 20]
      },
      {
        name: "订单量",
        data: [18, 15, 20, 30, 8, 15]
      }
    ]
  }
  
  // 饼图数据
  pieData.value = {
    series: [
      {
        name: "市场份额",
        data: [
          {name: '产品A', value: 50},
          {name: '产品B', value: 30},
          {name: '产品C', value: 20}
        ]
      }
    ]
  }
}

// 更新所有图表数据
const updateAllCharts = () => {
  // 更新折线图数据
  lineData.value = {
    categories: ["Q1", "Q2", "Q3", "Q4"],
    series: [
      {
        name: "销售额",
        data: [Math.random() * 50, Math.random() * 50, Math.random() * 50, Math.random() * 50]
      },
      {
        name: "订单量",
        data: [Math.random() * 50, Math.random() * 50, Math.random() * 50, Math.random() * 50]
      }
    ]
  }
  
  // 更新饼图数据
  pieData.value = {
    series: [
      {
        name: "市场份额",
        data: [
          {name: '产品A', value: Math.random() * 100},
          {name: '产品B', value: Math.random() * 100},
          {name: '产品C', value: Math.random() * 100}
        ]
      }
    ]
  }
}

onMounted(() => {
  initData()
})
</script>

<style>
.charts-container {
  padding: 20rpx;
}

.chart-wrapper {
  width: 100%;
  height: 500rpx;
  margin-bottom: 40rpx;
  background-color: #fff;
  border-radius: 12rpx;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
</style>

三、Vue 3 组合式函数封装

为了更好的复用代码,我们可以将图表逻辑封装成组合式函数:

1. 创建 useChart.js

// composables/useChart.js
import { ref } from 'vue'

export function useChart(chartType, defaultOpts = {}) {
  const chartData = ref({})
  const chartOpts = ref({
    color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE"],
    padding: [15, 15, 0, 15],
    ...defaultOpts
  })
  
  const updateChartData = (newData) => {
    chartData.value = newData
  }
  
  return {
    chartData,
    chartOpts,
    updateChartData
  }
}

2. 在组件中使用

<template>
  <view>
    <canvas
      canvasId="customChart"
      :type="chartType"
      :opts="chartOpts"
      :chartData="chartData"
      canvas2d
    />
    
    <button @click="updateData">更新数据</button>
  </view>
</template>

<script setup>
import { useChart } from '@/composables/useChart'

const { chartData, chartOpts, updateChartData } = useChart('column', {
  legend: {
    show: true,
    position: 'bottom'
  }
})

const updateData = () => {
  updateChartData({
    categories: ["A", "B", "C", "D"],
    series: [
      {
        name: "系列1",
        data: [Math.random() * 100, Math.random() * 100, Math.random() * 100, Math.random() * 100]
      }
    ]
  })
}
</script>

四、注意事项

  1. 微信小程序限制
    • 每个页面的 canvas 数量有限制(通常最多 5 个)
    • canvas 层级较高,会覆盖其他组件
  1. 性能优化
    • 对于复杂图表,考虑使用 web-view 加载 H5 页面
    • 避免频繁更新大数据量图表
  1. Vue 3 特有特性
    • 使用 refreactive 管理图表数据状态
    • 利用 watch 监听数据变化自动更新图表
    • 使用组合式函数提高代码复用性

TypeScript 支持

// 可以添加类型定义
interface ChartData {
  categories: string[]
  series: {
    name: string
    data: number[]
  }[]
}

const chartData = ref<ChartData>({ categories: [], series: [] })

通过以上 Vue 3 的写法,你可以更简洁、更高效地在 UniApp 微信小程序中使用 uCharts 图表组件。组合式 API 的使用让图表逻辑更容易封装和复用,使代码结构更加清晰。

五、性能优化建议

  1. 避免频繁更新:尽量减少图表更新的频率
  2. 合理使用 canvasId:多个图表需要不同的 canvasId
  3. 按需加载:只在需要显示的页面加载图表
  4. 简化数据:减少不必要的数据点
  5. 使用 canvas2d:微信小程序中优先使用 canvas2d 模式

六、常见问题解决

1. 图表不显示

  • 检查 canvasId 是否唯一
  • 确认 chartData 数据格式正确
  • 查看控制台是否有报错

2. 真机调试问题

  • 确保开启了 canvas2d 模式
  • 检查微信开发者工具的基础库版本

3. 图表渲染错位

  • 检查容器尺寸是否合理
  • 确认 padding 配置正确

七、总结

uCharts 在 UniApp 微信小程序中表现优秀,支持多种图表类型,性能良好。更多高级功能和详细配置可以参考 uCharts 官方文档

希望这篇文章能帮助你在项目中顺利使用 uCharts 图表组件!