在 uniapp 开发 H5 项目时,ECharts 折线图是数据可视化的常用组件,但移动端滑动缩放、触摸展示标签提示是很多开发者的痛点 —— 原生配置在 H5 端容易出现滑动冲突、提示框不显示、缩放不灵敏等问题。

本篇基于Vue3+TS+setup 语法糖,手把手教你实现适配 H5 的 ECharts 折线图,包含:
✅ 多系列平滑折线图样式定制
✅ X 轴水平滑动缩放(无页面滚动冲突)
✅ 移动端触摸精准显示 tooltip 标签
✅ 样式还原设计稿(图例、网格、坐标轴美化)
✅ 组件化封装 + 生命周期优化

最终效果

  1. 折线图展示身高 / 体重 / 肺活量三组数据,平滑曲线 + 高颜值样式
  2. 手指左右滑动图表,X 轴自动滚动缩放,只操作图表不影响页面
  3. 手指触摸图表任意数据点,精准弹出标签提示框
  4. 自适应屏幕尺寸,组件卸载自动销毁

一、前置准备

1. 安装 ECharts

在 uniapp 项目根目录执行安装命令:

npm install echarts --save

2. 环境说明

  • 框架:uniapp + Vue3 + TypeScript
  • 平台:H5 端
  • 图表:ECharts 5.x

二、完整代码实现

创建折线图组件(例:components/LineChart.vue),直接复制以下代码即可使用:

<script setup lang="ts">
import * as echarts from 'echarts'
import { ref, nextTick, onUnmounted, onLoad } from 'vue'

// 图表DOM引用
const chartRef = ref<HTMLDivElement>()
// 图表实例
let myChart: any = null

// ECharts配置项(核心:样式+滑动+提示框)
const option = ref<any>({
  // 折线颜色
  color: ['#3E77FA', '#6AD36A', '#F6BD16'],
  // 网格边距
  grid: {
    top: 47,
    left: 12,
    right: 12,
    bottom: 0,
    containLabel: true,
  },
  // 图例配置
  legend: {
    show: true,
    data: ['身高', '体重', '肺活量'],
    top: 6,
    left: 'center',
    icon: 'circle',
    itemWidth: 8,
    itemHeight: 8,
    itemGap: 32,
    textStyle: {
      color: '#46474C',
      fontSize: 12,
      fontWeight: 400,
      lineHeight: 32,
      fontFamily: 'PingFang SC, PingFang SC-400',
    },
  },
  // X轴配置
  xAxis: {
    type: 'category',
    data: ['2024-2025学1', '2024-2025学2', '2024-2025学3', '2024-2025学4', '2024-2025学5', '2024-2025学6', '2024-2025学7'],
    axisLabel: {
      color: '#303233',
      fontSize: 12,
      fontFamily: 'PingFang SC, PingFang SC-400',
    },
    axisLine: { show: false },
    splitLine: {
      show: true,
      lineStyle: { color: '#E6EAF3', width: 1 }
    }
  },
  // Y轴配置
  yAxis: {
    type: 'value',
    axisLine: {
      show: true,
      lineStyle: { color: '#E6EAF3', width: 1 }
    },
    axisLabel: { color: '#616366', fontSize: 12 },
    splitLine: { lineStyle: { color: '#E6EAF3', width: 1 } }
  },
  // 提示框tooltip(触摸显示标签)
  tooltip: {
    trigger: 'axis',
    triggerOn: 'mousemove|click|touchstart',
    axisPointer: {
      type: 'line',
      lineStyle: { color: '#999', width: 1, type: 'dashed' }
    },
    backgroundColor: 'rgba(255,255,255,0.95)',
    borderWidth: 1,
    textStyle: { color: '#333' },
    extraCssText: 'box-shadow: 0 2px 8px rgba(0,0,0,0.1);border-radius:4px;',
  },
  // 数据缩放滑动(核心:H5滑动配置)
  dataZoom: [
    {
      xAxisIndex: 0,
      type: 'inside', // 内置滑动,无需显示滑块
      startValue: '2024-2025学1', // 默认起始项
      endValue: '2024-2025学3', // 默认结束项
      enable: true,
      zoomLock: true, // 禁止缩放,仅允许滑动
      direction: 'horizontal', // 仅水平滑动
      throttle: 10, // 优化滑动流畅度
    },
  ],
  // 折线数据
  series: [
    {
      name: '身高',
      data: [82, 93, 90, 93, 120, 130, 130],
      type: 'line',
      smooth: true, // 平滑曲线
      symbol: 'none', // 隐藏数据点
      lineStyle: { width: 2 },
    },
    {
      name: '体重',
      data: [0, 9, 90, 93, 140, 230, 530],
      type: 'line',
      smooth: true,
      symbol: 'none',
      lineStyle: { width: 2 },
    },
    {
      name: '肺活量',
      data: [820, 932, 901, 934, 1290, 1330, 1320],
      type: 'line',
      smooth: true,
      symbol: 'none',
      lineStyle: { width: 2 },
    },
  ],
})

/**
 * 渲染图表
 */
const getRender = () => {
  nextTick(() => {
    if (!chartRef.value) return
    // 销毁旧实例,防止重复创建
    if (myChart) myChart.dispose()

    // 初始化图表(H5兼容配置)
    myChart = echarts.init(chartRef.value, null, {
      renderer: 'canvas',
      useDirtyRect: false,
    })
    myChart.setOption(option.value)

    // 监听窗口缩放
    window.addEventListener('resize', handleResize)
    // 绑定触摸事件(优化tooltip)
    bindTouchEvent()
  })
}

/**
 * 绑定触摸事件:解决H5端tooltip不显示问题
 */
let isTouching = false
const bindTouchEvent = () => {
  const chartDom = chartRef.value!
  // 触摸开始
  chartDom.addEventListener('touchstart', (e) => {
    isTouching = true
    handleTooltipOnTouch(e)
  })
  // 触摸滑动
  chartDom.addEventListener('touchmove', (e) => {
    if (isTouching) {
      e.preventDefault() // 阻止页面滚动
      handleTooltipOnTouch(e)
    }
  })
  // 触摸结束
  chartDom.addEventListener('touchend', () => {
    isTouching = false
    setTimeout(() => myChart?.dispatchAction({ type: 'hideTip' }), 1000)
  })
}

/**
 * 手动触发tooltip显示
 */
const handleTooltipOnTouch = (e: TouchEvent) => {
  if (!myChart) return
  const rect = chartRef.value!.getBoundingClientRect()
  const touch = e.touches[0]
  // 计算相对坐标
  const x = touch.clientX - rect.left
  const y = touch.clientY - rect.top
  // 调用ECharts显示提示框
  myChart.dispatchAction({
    type: 'showTip',
    x, y,
    position: [x + 10, y + 10],
  })
}

/**
 * 图表自适应
 */
const handleResize = () => myChart?.resize()

// 生命周期:页面加载渲染图表
onLoad(() => getRender())

// 生命周期:卸载组件,清理资源
onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  myChart?.dispose()
  myChart = null
})
</script>

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

<style lang="scss" scoped>
.line-chart {
  width: 100%;
  height: 380rpx; // 根据需求调整高度
}
</style>

三、核心功能解析

1. H5 端滑动缩放(无冲突)

关键配置在 dataZoom,解决图表滑动与页面滚动冲突问题:

dataZoom: [
  {
    type: 'inside', // 内置滑动,更美观
    zoomLock: true, // 锁定缩放,仅允许滑动
    direction: 'horizontal', // 仅水平方向
    throttle: 10, // 减少事件触发,提升流畅度
  }
]

2. 移动端触摸显示 tooltip 标签

原生 ECharts 在 H5 端触摸不触发提示框,我们通过手动绑定触摸事件 + 计算坐标实现精准显示:

  1. 监听 touchstart/touchmove/touchend
  2. 计算触摸点相对于图表的坐标
  3. 调用 dispatchAction 手动触发 showTip

3. 样式高度定制化

  • 隐藏默认坐标轴、自定义网格线颜色
  • 图例居中、圆形小图标、间距调整
  • 平滑折线、隐藏数据点,更符合移动端设计
  • tooltip 圆角 + 阴影,视觉更美观

4. 性能优化

  • 组件销毁时销毁图表实例,防止内存泄漏
  • 监听窗口变化,图表自动适配
  • 避免重复创建实例,保证流畅运行

四、使用方式

在页面中直接引入组件即可:

<template>
  <view class="page">
    <LineChart />
  </view>
</template>

<script setup lang="ts">
import LineChart from '@/components/LineChart.vue'
</script>

五、常见问题解决

1. 图表不显示 / 空白

  • 检查容器是否设置固定宽高(必须设置,否则无法渲染)
  • 确认 nextTick 中渲染,等待 DOM 加载完成
  • H5 端开启 canvas 渲染模式

2. 滑动时页面跟着滚动

  • 触摸事件中添加 e.preventDefault() 阻止默认滚动
  • dataZoom 配置 direction: 'horizontal' 限定方向

3. Tooltip 不显示 / 位置错乱

  • 使用手动触发 showTip 方式,不要依赖原生触摸
  • 正确计算触摸坐标(相对图表容器)

六、总结

这套代码完美解决了 uniapp H5 端 ECharts 折线图的滑动、触摸、样式、兼容四大核心问题,直接复制即可落地使用,支持多系列数据、自定义样式、动态数据修改。

如果你的项目需要柱状图、饼图,只需修改 series 和配置项即可快速适配,通用性极强!

更多推荐