Skip to content

故障排查

快速定位和解决常见问题。

诊断流程

按顺序检查:

控制台错误 → 数据格式 → 容器配置 → 浏览器兼容性

常见错误

"Cannot read property 'exportImage' of null"

原因:组件引用为空

解决

vue
<template>
  <!-- ❌ 错误:ref 名称不匹配 -->
  <RayBar ref="chart" :option="option" />
</template>

<script setup>
const chartRef = ref(null)  // 变量名和 ref 不一致
</script>

<!-- ✅ 正确:ref 名称匹配 -->
<template>
  <RayBar ref="chartRef" :option="option" />
</template>

<script setup>
const chartRef = ref(null)
</script>

"WebGL context lost"

原因:GPU 资源耗尽

解决:减少同时渲染的图表数量、降低图表复杂度、刷新页面释放资源

javascript
// 监听 WebGL 上下文丢失
window.addEventListener('webglcontextlost', (event) => {
  event.preventDefault()
  console.warn('WebGL 上下文丢失,请刷新页面')
  // 提示用户刷新
})

"Failed to compile shader"

原因:GPU 不支持某些特性

解决:关闭高级后处理效果、使用简单材质、检查浏览器和 GPU 驱动更新

javascript
const option = {
  series: [{ data: [120, 200, 150] }],
  postprocessing: {
    enable: false  // 关闭后处理
  }
}

渲染问题

图表显示全黑

可能原因:光照配置错误、材质颜色为黑色、相机位置不当

诊断

javascript
// 1. 检查是否手动配置了光照
const option = {
  series: [{ data: [120, 200, 150] }],
  // 移除 lights 配置,使用自动光照
  // lights: [...]  // 注释掉
}

// 2. 检查材质颜色
const option = {
  series: [{
    data: [120, 200, 150],
    color: ['#42b883']  // 确保不是黑色
  }]
}

// 3. 启用光源辅助器调试
const option = {
  series: [{ data: [120, 200, 150] }],
  showLightHelpers: true
}

图表闪烁或抖动

可能原因

  1. Z-fighting(深度冲突)
  2. 数据更新过于频繁
  3. 浏览器性能问题

解决

javascript
// 1. 调整 Z 轴偏移
const option = {
  series: [{
    data: [120, 200, 150],
    itemStyle: {
      polygonOffset: true,
      polygonOffsetFactor: -1,
      polygonOffsetUnits: -1
    }
  }]
}

// 2. 使用防抖更新数据
import { debounce } from 'lodash-es'

const updateChart = debounce((newData) => {
  option.value = {
    ...option.value,
    series: [{ data: newData }]
  }
}, 100)

图表模糊不清

可能原因:设备像素比问题、容器尺寸不当、抗锯齿未启用

解决

javascript
// 确保容器尺寸合适
<div style="width: 800px; height: 600px">
  <RayBar :option="option" width="100%" height="100%" />
</div>

// 检查设备像素比
console.log('设备像素比:', window.devicePixelRatio)
// 如果 > 2,可能需要调整渲染尺寸

数据问题

数据不显示

诊断清单

javascript
// ✅ 检查 1:数据格式正确
const option = {
  series: [{
    data: [120, 200, 150]  // 数字数组
  }],
  xAxis3D: {
    data: ['A', 'B', 'C']  // 类别数组
  }
}

// ✅ 检查 2:数据不为空
console.log('数据:', option.series[0].data)

// ✅ 检查 3:数据范围合理
// 如果数据都是 0 或非常小,可能看不见
const hasValidData = option.series[0].data.some(v => v > 0)
console.log('有有效数据:', hasValidData)

// ✅ 检查 4:坐标轴范围
const option = {
  series: [{ data: [120, 200, 150] }],
  yAxis3D: {
    min: 0,    // 确保包含数据范围
    max: 250
  }
}

数据更新不生效

常见错误

javascript
// ❌ 错误 1:直接修改数组
option.value.series[0].data.push(180)  // 不会触发更新

// ✅ 正确:创建新对象
option.value = {
  ...option.value,
  series: [{
    ...option.value.series[0],
    data: [...option.value.series[0].data, 180]
  }]
}

// ❌ 错误 2:修改嵌套属性
option.value.series[0].data[0] = 180  // 不会触发更新

// ✅ 正确:替换整个数组
option.value = {
  ...option.value,
  series: [{
    ...option.value.series[0],
    data: [180, 200, 150]
  }]
}

性能问题

帧率低(FPS < 30)

诊断工具

javascript
// 监控帧率
let lastTime = performance.now()
let frames = 0

function checkFPS() {
  frames++
  const now = performance.now()
  
  if (now >= lastTime + 1000) {
    const fps = Math.round((frames * 1000) / (now - lastTime))
    console.log('FPS:', fps)
    
    if (fps < 30) {
      console.warn('⚠️ 帧率过低,建议优化')
    }
    
    frames = 0
    lastTime = now
  }
  
  requestAnimationFrame(checkFPS)
}

checkFPS()

优化方案

javascript
// 1. 减少数据量
const optimizedData = largeData.filter((_, i) => i % 2 === 0)  // 采样

// 2. 简化材质
const option = {
  series: [{
    data: optimizedData,
    itemStyle: {
      metalness: 0,
      roughness: 1
    }
  }],
  postprocessing: {
    enable: false
  }
}

// 3. 降低渲染质量(移动端)
const isMobile = /Mobile|Android|iPhone/i.test(navigator.userAgent)
if (isMobile) {
  // 使用更小的尺寸
  <RayBar :option="option" width="100%" height="400px" />
}

内存泄漏

检查方法

javascript
// 1. 使用 Chrome DevTools Memory Profiler
// 2. 检查组件销毁时是否清理资源

// ✅ 正确:清理事件监听
<script setup>
import { onBeforeUnmount } from 'vue'

const chartRef = ref(null)
let unsubscribe = null

onMounted(() => {
  unsubscribe = chartRef.value?.on('click', handleClick)
})

onBeforeUnmount(() => {
  // 清理事件监听
  if (unsubscribe) {
    unsubscribe()
  }
})
</script>

配置问题

TypeScript 类型错误

常见问题

typescript
// ❌ 错误:类型不匹配
const option = {
  series: [{
    data: ['120', '200', '150']  // 字符串而非数字
  }]
}

// ✅ 正确:使用正确类型
const option: RayChartOption = {
  series: [{
    data: [120, 200, 150]  // 数字
  }]
}

// ✅ 使用类型断言(确定类型正确时)
const option = {
  series: [{
    data: rawData.map(Number)
  }]
} as RayChartOption

配置不生效

检查优先级

javascript
// 配置优先级:组件 props > series 配置 > 默认值

// 1. 组件 props 优先级最高
<RayBar :option="option" width="800px" />  // width 会覆盖 option 中的配置

// 2. series 配置优先级次之
const option = {
  series: [{
    data: [120, 200, 150],
    color: ['#42b883']  // 会覆盖默认颜色
  }]
}

// 3. 检查拼写错误
const option = {
  series: [{
    data: [120, 200, 150],
    itemStyle: {
      metalness: 0.8,  // ✅ 正确
      // metaless: 0.8  // ❌ 拼写错误,不会生效
    }
  }]
}

浏览器兼容性

检测 WebGL 支持

javascript
function checkWebGLSupport() {
  try {
    const canvas = document.createElement('canvas')
    const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl')
    
    if (!gl) {
      console.error('❌ 浏览器不支持 WebGL')
      return false
    }
    
    console.log('✅ WebGL 支持正常')
    console.log('WebGL 版本:', gl.getParameter(gl.VERSION))
    console.log('着色器版本:', gl.getParameter(gl.SHADING_LANGUAGE_VERSION))
    console.log('渲染器:', gl.getParameter(gl.RENDERER))
    
    return true
  } catch (e) {
    console.error('❌ WebGL 检测失败:', e)
    return false
  }
}

// 在应用启动时检查
if (!checkWebGLSupport()) {
  alert('您的浏览器不支持 WebGL,无法使用 3D 图表功能')
}

移动端特殊处理

javascript
const isMobile = /Mobile|Android|iPhone/i.test(navigator.userAgent)
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent)

const option = {
  series: [{
    data: isMobile ? sampledData : fullData
  }],
  postprocessing: {
    enable: !isMobile  // 移动端关闭后处理
  },
  controlSettings: {
    enableRotate: true,
    enableZoom: !isIOS,  // iOS 缩放可能有问题
    enablePan: true
  }
}

调试技巧

启用详细日志

javascript
// 在开发环境启用详细日志
if (import.meta.env.DEV) {
  console.log('图表配置:', option)
  console.log('图表引用:', chartRef.value)
}

使用 Vue DevTools

  1. 安装 Vue DevTools 浏览器扩展
  2. 检查组件树中的 RayChart 组件
  3. 查看 props 和 data 是否正确

性能分析

javascript
// 使用 Performance API
performance.mark('chart-start')

// 渲染图表
await nextTick()

performance.mark('chart-end')
performance.measure('chart-render', 'chart-start', 'chart-end')

const measure = performance.getEntriesByName('chart-render')[0]
console.log('渲染耗时:', measure.duration, 'ms')

获取帮助

以上方法都无法解决时:

  1. 查看文档:https://docs.raychart.cn
  2. 查看示例:https://raychart.cn/gallery
  3. 检查版本:确保使用最新版本
  4. 提供信息:RayChart 版本、浏览器版本、错误信息、最小可复现示例

相关资源