Skip to content

高级功能

RayChart 提供一组面向进阶场景的工具 API:性能监控、数据验证、对象池、WebGL 能力检测与数据缓存。常规图表开发用不到这些功能,遇到下述具体问题时再查阅对应章节。

什么时候需要本页内容

  • 图表卡顿,想定位耗时瓶颈
  • 用 JavaScript(非 TypeScript)开发,想在校验配置错误
  • 编写高频创建临时对象的自定义 3D 动画
  • 需要兼容老旧浏览器,检测 WebGL 能力
  • 轮询数据时避免无意义的重复渲染

只画常规图表?直接看快速上手


性能监控

方法级计时:DEV_MONITOR / globalMonitor

用于定位某段代码(如更新数据、重渲染)的耗时。

ts
import { DEV_MONITOR } from 'raychart'

function updateChart() {
  const startTime = DEV_MONITOR.start('更新数据')
  chartOption.value = { series: [{ data: newData }] }
  DEV_MONITOR.end('更新数据', startTime) // 开发环境打印耗时(毫秒)
}

也可用 measure 包裹函数自动计时:

ts
import { DEV_MONITOR } from 'raychart'

DEV_MONITOR.measure('更新数据', () => {
  chartOption.value = { series: [{ data: newData }] }
})

开发环境专用

DEV_MONITOR 在开发环境等价于 globalMonitor;生产构建中所有方法为空操作(start/end 返回 0),不产生任何开销。生产环境需要采样时,可自行创建 new PerformanceMonitor(true)

读取某个标签的统计(getStats 需传入标签名,无数据时返回 null):

ts
import { globalMonitor } from 'raychart'

const stats = globalMonitor.getStats('更新数据')
if (stats) {
  console.log(`平均: ${stats.avg.toFixed(2)}ms,最大: ${stats.max.toFixed(2)}ms,采样 ${stats.count} 次`)
}

// 打印全部标签的报告到控制台
globalMonitor.printReport()

// 清除统计(不传参数则全部清除)
globalMonitor.clear('更新数据')

PerformanceMetric 字段:count(采样次数)、total / avg(总耗时 / 平均耗时)、min / maxlast(最近一次),单位均为毫秒。

FPS 与内存监控

RayChart 内置独立的 FPS 与内存(Chrome 系浏览器)监控器:

ts
import { globalFPSMonitor, globalMemoryMonitor } from 'raychart'

// FPS:在渲染循环中调用 tick() 采样,保留最近 60 帧
function renderLoop() {
  globalFPSMonitor.tick()
  const fps = globalFPSMonitor.getAverageFPS()
  requestAnimationFrame(renderLoop)
}

// 内存:仅支持提供 performance.memory 的浏览器(Chrome/Edge),其他环境返回 null
const usage = globalMemoryMonitor.getMemoryUsage()
if (usage) {
  console.log('已用堆内存:', globalMemoryMonitor.formatBytes(usage.usedJSHeapSize))
}

数据验证

用 JavaScript 开发且担心配置写错时,可手动校验配置。TypeScript 用户编辑器会直接提示,无需此功能。

ts
import { DataValidator, CommonRules } from 'raychart'

const option = {
  series: [{ data: [1, 2, 3] }],
}

const schema = {
  series: CommonRules.required('series 不能为空'),
  'series.0.data': CommonRules.array(1, undefined, '至少一个数据点'),
  'series.0.itemStyle.metalness': CommonRules.percentage('metalness 需在 0-100 之间'),
}

// 方式一:返回校验结果,不抛错
const result = DataValidator.validate(option, schema)
if (!result.valid) {
  result.errors.forEach((e) => console.log(`${e.path}: ${e.message}`))
}

// 方式二:校验失败直接抛异常
try {
  DataValidator.validateOrThrow(option, schema)
} catch (error) {
  console.error('图表配置错误:', (error as Error).message)
}

图表组件已内置校验

各图表在 setOption 时已自动校验关键字段(如系列必填、数据非空、类型枚举),校验失败会抛出带图表类型的错误。手动调用适用于需要自定义规则的场景。

CommonRules 预设规则:required / string / number(min?, max?) / array(minLength?, maxLength?) / enum(values) / positive / percentage / color,完整说明见 工具方法 API


对象池

为什么需要对象池

高频动画循环中反复 new 临时对象(Vector3Color 等)会产生大量垃圾,触发频繁 GC 导致卡顿:

ts
// 不推荐:每帧创建 1000 个临时向量,产生大量垃圾
function animate() {
  for (let i = 0; i < 1000; i++) {
    const v = new THREE.Vector3(x, y, z)
    const length = v.length()
  }
}

推荐用法:withPooled 自动管理

从池中取对象、调用回调后自动归还,无需手动释放:

ts
import { withPooledVector3 } from 'raychart'

const length = withPooledVector3((v) => {
  v.set(x, y, z)
  return v.length()
}) // 回调结束后 v 自动归还池中

同时使用多个向量时,回调参数为向量数组,按序解构使用:

ts
import { withPooledVectors } from 'raychart'

const newPos = withPooledVectors(3, ([pos, velocity, force]) => {
  pos.copy(particle.position)
  velocity.copy(particle.velocity)
  force.set(0, -9.8, 0) // 重力
  velocity.add(force)
  pos.add(velocity)
  return pos.clone() // 注意:clone 出的新对象不来自池中,用完自行释放或复用
})

手动管理(不推荐)

ts
import { vector3Pool } from 'raychart'

const v = vector3Pool.acquire() // 从池中取一个 Vector3
v.set(1, 2, 3)
const length = v.length()
vector3Pool.release(v) // 必须归还,否则池会逐渐枯竭

注意

手动管理容易遗漏 release()。请优先使用 withPooled* 自动管理。

内置对象池

名称说明
withPooledVector3(fn) / withPooledVector2(fn)自动取还 3D / 2D 向量
withPooledColor(fn)自动取还颜色
withPooledVectors(count, fn)批量取用多个向量,回调收到数组
vector3Pool / vector2Pool / colorPool手动管理的向量 / 颜色池
quaternionPool / matrix4Pool / eulerPool四元数 / 矩阵 / 欧拉角池
box3Pool / spherePool包围盒 / 球池

自定义对象池

ts
import { ObjectPool } from 'raychart'

class Particle {
  x = 0
  y = 0
  speed = 0

  reset() {
    this.x = 0
    this.y = 0
    this.speed = 0
  }
}

// 构造签名:new ObjectPool(factory, maxSize?, reset?)
// 第二个参数是池容量(默认 100),第三个参数在对象归还时调用
const particlePool = new ObjectPool(() => new Particle(), 100, (p) => p.reset())

const p = particlePool.acquire() // 从池中取对象(池空时走 factory 创建)
p.x = Math.random() * 100
// ... 使用
particlePool.release(p) // 归还(超过容量上限时直接丢弃)

WebGL 能力检测

检测是否支持

ts
import { checkWebGLSupport } from 'raychart'

const support = checkWebGLSupport()
if (!support.supported) {
  // 不支持 WebGL:提示用户升级浏览器
  console.error('浏览器不支持 WebGL')
} else {
  console.log(`支持 WebGL ${support.version}.0`)
}

获取详细能力

ts
import { getWebGLCapabilities } from 'raychart'

const caps = getWebGLCapabilities() // 不支持时返回 null
if (caps) {
  console.log('最大纹理尺寸:', caps.maxTextureSize)
  console.log('最大顶点属性数:', caps.maxVertexAttributes)
  console.log('支持浮点纹理:', caps.extensions.floatTextures)
  console.log('支持各向异性过滤:', caps.extensions.anisotropicFiltering)
}

extensions 为对象,字段包括 floatTextureshalfFloatTexturesdepthTextureinstancedArraysanisotropicFiltering 等,完整定义见 工具方法 API

检查指定扩展

ts
import { checkRequiredExtensions } from 'raychart'

const result = checkRequiredExtensions(['OES_texture_float', 'WEBGL_depth_texture'])
if (result.supported) {
  console.log('所有扩展均支持')
} else {
  console.log('缺少扩展:', result.missing)
}

获取推荐的渲染器配置

按设备能力返回推荐配置(移动端自动降低质量):

ts
import { getRecommendedRendererConfig } from 'raychart'

const config = getRecommendedRendererConfig()
// { antialias: boolean, powerPreference: 'high-performance' | 'low-power' | 'default', precision: 'highp' | 'mediump' | 'lowp' }
console.log(config)

打印完整能力信息(调试用)

ts
import { printWebGLCapabilities } from 'raychart'

printWebGLCapabilities() // 在控制台分组打印 WebGL 版本、限制与扩展支持

自动适配

图表组件初始化时已自动检测并适配设备能力,无需手动调用。仅在需要自定义降级策略时使用以上 API。


数据缓存

轮询或高频 setOption 时,可用 globalDataCache 判断数据是否真正变化,跳过无意义的重复渲染:

ts
import { globalDataCache } from 'raychart'

setInterval(() => {
  const newData = fetchData() // 轮询获取数据

  // 数据内容有变化才更新图表
  if (globalDataCache.hasChanged('myChart', newData)) {
    chartOption.value = { series: [{ data: newData }] }
    globalDataCache.set('myChart', newData)
  }
}, 1000)

其他方法:

ts
import { globalDataCache } from 'raychart'

// 读取缓存
const cached = globalDataCache.get('myChart')

// 删除单个缓存
globalDataCache.delete('myChart')

// 清空全部缓存(clear 不接受参数)
globalDataCache.clear()

组件已内置

BaseChart.setOption 内部已用相同机制对 option 做内容哈希比对,内容未变化时自动跳过重渲染(开发环境控制台会打印 Data unchanged, skipping render)。手动使用缓存适用于组件之外的场景。

也可创建独立实例(可设置容量与过期时间,默认 50 条 / 5 分钟):

ts
import { DataCache } from 'raychart'

const cache = new DataCache(200) // 容量 200,超过自动淘汰最久未使用的条目

完整 API 列表

性能监控

  • DEV_MONITOR - 开发环境计时工具(生产环境为空操作)
  • globalMonitor - 全局方法级计时监控器
  • globalFPSMonitor - 全局 FPS 监控器(tick / getAverageFPS / getCurrentFPS / getMinFPS
  • globalMemoryMonitor - 全局内存监控器(getMemoryUsage / formatBytes / printMemoryUsage,仅 Chrome 系浏览器)

数据验证

  • DataValidator - 配置验证工具(validate / validateOrThrow
  • CommonRules - 常用验证规则预设

Three.js 对象池(自动管理)

  • withPooledVector3() / withPooledVector2() / withPooledColor() / withPooledVectors()

Three.js 对象池(手动管理)

  • vector3Pool / vector2Pool / colorPool / quaternionPool / matrix4Pool / eulerPool / box3Pool / spherePool
  • ObjectPool - 自定义对象池类

WebGL 能力检测

  • checkWebGLSupport() - 检查是否支持 WebGL
  • getWebGLCapabilities() - 获取详细能力
  • checkRequiredExtensions() - 检查指定扩展
  • printWebGLCapabilities() - 打印完整信息
  • getRecommendedRendererConfig() - 推荐渲染器配置

数据缓存

  • globalDataCache - 全局缓存实例
  • DataCache - 缓存类(可创建独立实例)

总结

功能适用场景难度
性能监控图表卡顿,定位耗时瓶颈⭐ 简单
数据验证JS 开发,担心配置写错⭐ 简单
WebGL 检测兼容老旧浏览器⭐ 简单
数据缓存轮询数据,避免重复渲染⭐⭐ 中等
对象池高频创建临时对象的自定义动画⭐⭐⭐ 较难

记住

常规图表开发无需使用这些功能,遇到对应问题时再回来看对应章节。


相关文档