用途
这是一套可复用的 Studio 图表性能审计与修复工作流,来自 bklit/bklit-ui。当某个图表在 Studio 中显得迟钝——例如平移、拖动滑块刻度、图例悬停时不流畅——而同类图表(如饼图 pie-chart)表现正常时,使用本工作流定位并修复性能问题。
核心原则
一句话规则:如果需要,保留路径上的 enter 动画;随后取消 Motion 路径订阅并隔离悬停,使 Studio 滑块和图例更新不会每帧对每个系列重新执行昂贵的弧线/路径数学计算。
主要能力
工作流分为六个步骤。
1. 找出每次交互时重新渲染的内容
Studio 在每次滑块刻度以及图例/扇区悬停时都会更新 displayState。需要追踪:悬停是否与数据、比例尺、动画配置处于同一 context?预览是否每次渲染都重建子元素(data.map、pattern defs、motion props)?图表是否不必要地重新挂载(key 绑定到 motion 签名而非手动重放)?
模式:像 cartesian / pie 图表那样拆分 context——稳定的切片(data、geometry、动画配置)与悬停切片(hoveredIndex、tooltip)分开。不需要悬停的消费者只使用稳定 hook(usePieStable、useRingStable、useChartStable 等)。
Studio 平移:将图表渲染包裹在 StudioChartRender(packages/studio/src/components/studio-chart-render.tsx)中,这样当 render props 未变化时,camera pan / FPS 计数器父级更新会跳过图表树。
2. 将 SVG path d 动画视为昂贵操作
用 Motion / useTransform + d3 arc(或类似方式)动画 d 会每帧、每个系列执行布局和绘制。
推荐做法:悬停使用 transform / opacity(对合成器友好);enter 完成后使用静态 d;仅 enter 动画然后静态路径。
避免做法:enter 完成后持续进行 d 变形;在图表生命周期内一直保持 d 上的 Motion 订阅;无关 prop 变化时重新运行 enter 路径数学。
模式:enter 使用 useMountProgress,当 progress ≥ 1(useEnterComplete)时渲染静态路径,并仅在 motion.g 包裹层上用 x/y/opacity/scale 动画悬停(而非对 motion.path 逐路径缩放)。
共享 hook:packages/ui/src/charts/use-enter-complete.ts
3. 记忆化图表外壳 context
未记忆化的 provider 值会强制所有子元素在每次父级渲染时进行协调。用显式依赖(data、arcs/radii、尺寸、回调)记忆化稳定 context 对象;基于 hoveredIndex 与稳定的 setHoveredIndex(chart shell 中的 useCallback)记忆化悬停 context;将 isLoaded 与 ring/cartesian 对齐:使用 useEffect + timeout,而非惰性 useState 初始化器。
参考:pie-context.tsx、ring-context.tsx、chart-context.tsx、PieChartCore / RingChartCore 中对 provider 值的 useMemo。
4. Studio 预览专属优化
与图表无关,可在 packages/studio/src/components/charts/-studio.tsx 中应用:条件化 defs,仅当系列使用图案时才传入 patternDefs / gradients;记忆化派生数据(着色/映射后的数据数组,slice/系列列表,useMemo,依赖为 dataSeed + 影响颜色的 design 字段);记忆化 motion enter,不要内联调用 getStudioMotionEnterProps,而是用 useMemo,依赖仅为 motion 相关(而非完整 state);记忆化图例悬停,在 useMemo 中使用 { hoveredIndex, setHoveredIndex }(已在 studio-legend-hover.tsx 中);记忆化图表主体,使用 memo() 包裹,传入原始值(chartKey、chartSize、data)而非整个 ctx,使 pan/shell 重渲染跳过重建;在 Studio 中禁用 glow,在系列组件上设置 showGlow={false}。
参考:pie-studio-preview.tsx、ring-studio-preview.tsx。
5. 在 Studio 中与“快速”同类图表对比
将慢图表与同一编辑器中感觉流畅的图表(通常是 pie-chart)进行 diff。检查项包括:外壳(慢图表常见内联渲染、额外 defs;快图表常见 StudioChartShell + 条件图案)、系列数量(慢图表常见许多动画路径;快图表常见较少路径或更简单几何)、悬停(慢图表常见 context + 整树重渲染;快图表常见稳定订阅者,悬停基于 motion.g / translate)、enter(慢图表常见逐系列路径 d 擦除;快图表常见 enter 后静态 d,仅 transform 悬停)、平移(慢图表常见图表树每帧重建;快图表常见 StudioChartRender memo 边界)。
6. 验证标准
打开 PR 前执行:pnpm lint;pnpm --filter @bklitui/ui check-types;pnpm --filter @bklitui/studio check-types;当触及 studio/web 时进行范围化生产构建。
手动在 /studio?chart=<slug> 检查:enter 动画;悬停 / 图例同步;拖动几何滑块(无不必要重新挂载);enter 后画布平移(空格 + 拖动),FPS 接近 pie-chart 基线;若支持则检查图案/渐变模式。
图表状态(bklit-ui)
Pie(pie-chart):✅ 参考(#120)。Ring(ring-chart):✅ 已对齐清单(context 拆分、静态路径、StudioChartRender、预览记忆化)。Radar / Funnel / Choropleth(various):部分——运行清单。Cartesian / scatter / live-line(various):✅ #91 抽稀 + 悬停批处理。Sankey(sankey-chart):链接 stroke 上使用 useTransform——useEnterComplete 的候选对象。Gauge(gauge-chart):低优先级(单弧)。
关键文件
enter-complete hook:packages/ui/src/charts/use-enter-complete.ts。Pie 参考:packages/ui/src/charts/pie-slice.tsx、pie-context.tsx、pie-studio-preview.tsx。Ring:packages/ui/src/charts/ring.tsx、ring-chart.tsx、ring-studio-preview.tsx。平移隔离:packages/studio/src/components/studio-chart-render.tsx。注册表:packages/studio/src/lib/registry.tsx。
适用场景与限制
适用于 bklit-ui 的 Studio 图表性能问题审计与修复,尤其是交互卡顿而同类图表流畅的情况。资料未提供该工作流对非 bklit-ui 项目的通用性说明,也未提供具体的性能基准数值、收费或价格信息。