Appearance
性能优化
RayChart 内置多项性能优化,但处理大数据量时,仍需注意以下几点。
数据量控制
建议的数据量
- 柱状图/折线图: 建议不超过 1000 个数据点
- 散点图: 建议不超过 5000 个数据点
- 饼图: 建议不超过 50 个分类
- 雷达图: 建议不超过 20 个指标
数据采样
大数据量时用采样减少渲染:
javascript
// 原始数据
const rawData = Array.from({ length: 10000 }, (_, i) => i)
// 采样到 1000 个点
const sampledData = rawData.filter((_, i) => i % 10 === 0)
const option = {
series: [{
data: sampledData
}],
xAxis3D: {
type: 'value'
}
}数据聚合
将数据聚合到更粗的粒度:
javascript
// 按小时聚合分钟数据
const aggregatedData = minuteData.reduce((acc, item, i) => {
const hourIndex = Math.floor(i / 60)
if (!acc[hourIndex]) {
acc[hourIndex] = { sum: 0, count: 0 }
}
acc[hourIndex].sum += item.value
acc[hourIndex].count++
return acc
}, []).map(item => item.sum / item.count)渲染优化
避免频繁更新
javascript
// ❌ 不好的做法
setInterval(() => {
chartOption.value = { ...chartOption.value, series: [newData] }
}, 100)
// ✅ 好的做法
setInterval(() => {
chartOption.value = { ...chartOption.value, series: [newData] }
}, 1000)使用 v-if 而非 v-show
vue
<!-- ❌ 不好的做法 -->
<RayBar v-show="visible" :option="option" />
<!-- ✅ 好的做法 -->
<RayBar v-if="visible" :option="option" />及时销毁
vue
<script setup>
import { ref, onUnmounted } from 'vue'
const chartRef = ref()
onUnmounted(() => {
// 组件销毁时清理资源
chartRef.value?.dispose()
})
</script>资源管理
LRU 缓存
RayChart 用 LRU(最近最少使用)缓存自动管理资源:
- 材质复用 - 相同配置的材质会被复用
- 几何体复用 - 相同形状的几何体会被复用
- 自动清理 - 未使用的资源会被自动清理
缓存配置
javascript
// 默认配置
{
cacheSize: 100 // 每种资源类型最多缓存 100 个
}性能数据
| 场景 | 优化前 | 优化后 | 提升 |
|---|---|---|---|
| 缓存命中率 | ~70% | ~85% | +21% |
| 内存使用(1h) | 150MB | 95MB | -37% |
| 内存使用(4h) | 300MB+ | 110MB | -63% |
性能监控
使用性能监控
RayChart 内置性能监控:
javascript
import { globalMonitor } from 'raychart'
// 获取性能统计
const stats = globalMonitor.getStats()
console.log('FPS:', stats.fps)
console.log('Memory:', stats.memory)
console.log('Render time:', stats.renderTime)监控指标
- FPS - 帧率,建议保持在 30+ FPS
- Memory - 内存使用,监控是否有内存泄漏
- Render Time - 渲染时间,单帧渲染时间
性能分析
javascript
// 开始性能分析
const startTime = globalMonitor.start('myOperation')
// 执行操作
// ...
// 结束性能分析
globalMonitor.end('myOperation', startTime)
// 获取统计
const stats = globalMonitor.getOperationStats('myOperation')
console.log('Average time:', stats.averageTime)
console.log('Total calls:', stats.totalCalls)图表配置优化
降低复杂度
javascript
// ❌ 高复杂度
{
series: [{
data: largeDataset,
itemStyle: {
metalness: 0.8,
roughness: 0.2,
// 复杂的材质配置
}
}],
postprocessing: {
enable: true,
bloom: { enable: true },
SSAO: { enable: true } // 性能消耗大
}
}
// ✅ 优化后
{
series: [{
data: sampledDataset, // 采样后的数据
itemStyle: {
metalness: 0.3,
roughness: 0.5
}
}],
postprocessing: {
enable: true,
FXAA: { enable: true } // 仅启用轻量级效果
}
}简化光照
javascript
// ❌ 过多光源 - 手动配置过多光源
{
series: [{ data: [120, 200, 150] }],
lights: [
{ type: 'Ambient', intensity: 0.3 },
{ type: 'Directional', intensity: 1.0, position: { x: 5, y: 10, z: 5 } },
{ type: 'Point', intensity: 0.8, position: { x: -5, y: 5, z: 5 } },
{ type: 'Point', intensity: 0.6, position: { x: 5, y: 5, z: -5 } },
{ type: 'Spot', intensity: 1.0, position: { x: 0, y: 10, z: 0 } }
]
}
// ✅ 使用默认光照 - 框架自动配置
{
series: [{ data: [120, 200, 150] }],
xAxis3D: { data: ['A', 'B', 'C'] }
// 光照会自动配置,无需手动指定
}移动端优化
检测设备
javascript
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
const option = {
series: [{
data: isMobile ? sampledData : fullData
}],
xAxis3D: {
data: categories
},
postprocessing: {
enable: !isMobile // 移动端禁用后处理
},
controlSettings: {
rotateSpeed: isMobile ? 0.5 : 1.0 // 移动端降低速度
}
}降低分辨率
vue
<template>
<RayBar
:option="option"
:width="isMobile ? '100%' : '800px'"
:height="isMobile ? '400px' : '600px'"
/>
</template>性能检查清单
开发阶段
- [ ] 数据量是否在建议范围内
- [ ] 是否使用了数据采样或聚合
- [ ] 是否避免了频繁更新
- [ ] 是否正确使用 v-if
- [ ] 是否在组件销毁时清理资源
优化阶段
- [ ] 是否启用了性能监控
- [ ] FPS 是否稳定在 30+
- [ ] 内存使用是否稳定
- [ ] 是否简化了光照配置
- [ ] 是否按需启用后处理效果
移动端
- [ ] 是否检测了移动设备
- [ ] 是否降低了数据量
- [ ] 是否禁用了后处理
- [ ] 是否降低了交互速度
- [ ] 是否测试了实际设备
性能基准
桌面端(推荐配置)
- CPU: Intel i5 或同等性能
- GPU: 独立显卡或集成显卡
- 内存: 8GB+
- 浏览器: Chrome/Firefox/Edge 最新版
性能表现:
- 1000 数据点: 60 FPS
- 5000 数据点: 30-60 FPS
- 10000 数据点: 需要优化
移动端(推荐配置)
- 设备: iPhone 8+ / Android 中高端设备
- 浏览器: Safari/Chrome 最新版
性能表现:
- 500 数据点: 30-60 FPS
- 1000 数据点: 需要优化
- 建议禁用后处理效果
常见问题
Q: 图表卡顿怎么办?
A:
- 减少数据量
- 禁用后处理效果
- 简化光照配置
- 降低更新频率
Q: 内存持续增长?
A:
- 检查是否有内存泄漏
- 确保组件销毁时调用 dispose()
- 避免创建过多图表实例
Q: 移动端性能差?
A:
- 大幅减少数据量
- 禁用所有后处理效果
- 使用简单的材质配置
- 降低分辨率
性能优化案例
案例 1: 大数据量折线图
问题: 10000 个数据点导致卡顿
解决方案:
javascript
// 使用道格拉斯-普克算法简化曲线
const simplifiedData = simplifyPolyline(rawData, tolerance)
const option = {
series: [{
data: simplifiedData // 简化后约 500 个点
}],
xAxis3D: {
type: 'value'
}
}结果: FPS 从 15 提升到 60
案例 2: 多图表页面
问题: 页面有 10 个图表,内存占用高
解决方案:
vue
<template>
<div v-for="chart in visibleCharts" :key="chart.id">
<component :is="chart.component" v-if="chart.visible" :option="chart.option" />
</div>
</template>
<script setup>
import { RayBar, RayLine, RayPie } from 'raychart'
// 使用虚拟滚动,只渲染可见的图表
const visibleCharts = computed(() => {
return charts.value.filter(chart => isInViewport(chart))
})
</script>结果: 内存占用从 800MB 降到 200MB
