bklit-studio-chart-performance
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseStudio chart performance
Studio 图表性能
Use when a chart feels sluggish in Studio but similar charts (e.g. pie-chart) are fine.
当Studio中的图表运行卡顿,但同类图表(如饼图)运行正常时使用本方案。
One-line rule
一句话准则
Keep enter animation on paths if you need it, then drop Motion path subscriptions and isolate hover so Studio slider and legend updates don't replay expensive arc/path math across every series every frame.
如果需要路径的入场动画,请保留该动画,然后移除Motion路径订阅并隔离悬停逻辑,这样Studio滑块和图例更新时,就不会在每一帧都对所有系列重复执行高开销的圆弧/路径计算。
1. Find what re-renders on every interaction
1. 找出每次交互时会重新渲染的内容
Studio updates on every slider tick and on legend/slice hover. Trace:
displayState- Does hover live in the same context as data, scales, and animation config?
- Does the preview recreate children (, pattern defs, motion props) every render?
data.map - Does the chart remount unnecessarily (tied to motion signature vs manual replay)?
key
Pattern: Split context like cartesian / pie charts — stable slice (data, geometry, animation config) vs hover slice (, tooltip). Consumers that don't need hover use only the stable hook (, , , …).
hoveredIndexusePieStableuseRingStableuseChartStableStudio pan: Wrap chart render in () so camera pan / FPS counter parent updates skip the chart tree when render props are unchanged.
StudioChartRenderpackages/studio/src/components/studio-chart-render.tsxStudio会在每次滑块刻度变化、图例/切片悬停时更新。排查方向:
displayState- 悬停逻辑是否与数据、比例尺、动画配置处于同一上下文?
- 预览是否会在每次渲染时重新创建子组件(、图案定义、motion属性)?
data.map - 图表是否会不必要地重新挂载(绑定到motion签名而非手动重放)?
key
模式: 像笛卡尔图/饼图那样拆分上下文 —— 稳定切片(数据、几何形状、动画配置) vs 悬停切片(、提示框)。不需要悬停功能的消费者仅使用稳定钩子(、、等)。
hoveredIndexusePieStableuseRingStableuseChartStableStudio平移: 将图表渲染包裹在()中,这样相机平移/FPS计数器父组件更新时,若渲染属性未变化,就会跳过图表树的更新。
StudioChartRenderpackages/studio/src/components/studio-chart-render.tsx2. Treat SVG path d
animation as expensive
d2. 视SVG路径d
动画为高开销操作
dAnimating with Motion / + d3 arc (or similar) runs layout + paint every frame, per series.
duseTransform| Prefer | Avoid |
|---|---|
| Continuous |
Static | Keeping Motion subscriptions on |
| Enter animation only, then static paths | Re-running enter path math on unrelated prop changes |
Pattern: for enter → when progress ≥ 1 (), render static paths and only animate hover with /// on a wrapper (not per-path on ).
useMountProgressuseEnterCompletexyopacityscalemotion.gscalemotion.pathShared hook:
packages/ui/src/charts/use-enter-complete.ts使用Motion / + d3 arc(或类似工具)对属性进行动画,会在每一帧对每个系列执行布局+绘制操作。
useTransformd| 推荐方案 | 避免操作 |
|---|---|
使用 | 入场完成后持续对 |
入场完成后使用静态 | 在图表生命周期内保持对 |
| 仅保留入场动画,之后使用静态路径 | 在无关属性变化时重新执行入场路径计算 |
模式: 使用处理入场动画 → 当进度≥1时(通过判断),渲染静态路径,并仅在****容器上使用///实现悬停动画(而非在每个上单独设置)。
useMountProgressuseEnterCompletemotion.gxyopacityscalemotion.pathscale共享钩子:
packages/ui/src/charts/use-enter-complete.ts3. Memoize chart shell context
3. 记忆化图表外壳上下文
Unmemoized provider values force all children to reconcile on every parent render.
- Memoize the stable context object with explicit deps (data, arcs/radii, dimensions, callbacks).
- Memoize hover context on + stable
hoveredIndex(setHoveredIndexin chart shell).useCallback - Match to ring/cartesian:
isLoaded+ timeout, not a lazyuseEffectinitializer.useState
Reference: , , , / on provider value.
pie-context.tsxring-context.tsxchart-context.tsxPieChartCoreRingChartCoreuseMemo未记忆化的提供者值会强制所有子组件在每次父组件渲染时重新协调。
- 使用显式依赖项(数据、圆弧/半径、尺寸、回调)记忆化稳定上下文对象。
- 基于和稳定的
hoveredIndex(图表外壳中的setHoveredIndex)记忆化悬停上下文。useCallback - 匹配环形图/笛卡尔图的****逻辑:使用
isLoaded+ 超时,而非惰性useEffect初始化器。useState
参考实现:、、、 / 中对提供者值使用。
pie-context.tsxring-context.tsxchart-context.tsxPieChartCoreRingChartCoreuseMemo4. Studio preview–specific wins
4. Studio预览专属优化技巧
Chart-agnostic; apply in :
packages/studio/src/components/charts/*-studio*.tsx| Win | How |
|---|---|
| Conditional defs | Only pass |
| Memo derived data | Colored/mapped data arrays; slice/series lists ( |
| Memo motion enter | Don't call |
| Memo legend hover | |
| Memo chart body | |
| Disable glow in Studio | |
Reference: ,
pie-studio-preview.tsxring-studio-preview.tsx与图表类型无关;可在中应用:
packages/studio/src/components/charts/*-studio*.tsx| 优化点 | 实现方式 |
|---|---|
| 条件式定义 | 仅当系列使用图案时才传递 |
| 记忆化衍生数据 | 着色/映射后的数数组、切片/系列列表(使用 |
| 记忆化motion入场属性 | 不要内联调用 |
| 记忆化图例悬停 | 在 |
| 记忆化图表主体 | 使用 |
| 在Studio中禁用发光效果 | 在系列组件上设置 |
参考实现:、
pie-studio-preview.tsxring-studio-preview.tsx5. Compare against a “fast” sibling in Studio
5. 与Studio中“性能优异”的同类图表对比
Diff the slow chart against one that feels smooth in the same editor (usually pie-chart):
| Check | Slow chart often has | Fast chart often has |
|---|---|---|
| Shell | Inline render, extra defs | |
| Series count | Many animated paths | Fewer paths or simpler geometry |
| Hover | Context + full tree re-render | Stable subscribers; hover on |
| Enter | Path | Static |
| Pan | Chart tree rebuilds every frame | |
将卡顿的图表与同一编辑器中运行流畅的图表(通常是饼图)进行对比:
| 检查项 | 卡顿图表通常存在的问题 | 流畅图表通常具备的特征 |
|---|---|---|
| 外壳 | 内联渲染、冗余定义 | |
| 系列数量 | 大量带动画的路径 | 路径更少或几何形状更简单 |
| 悬停 | 上下文触发整树重新渲染 | 稳定的订阅者;在 |
| 入场动画 | 每个系列都有路径 | 入场后使用静态 |
| 平移 | 图表树每帧都重建 | |
6. Validation bar
6. 验证标准
Before opening a PR:
bash
pnpm lint
pnpm --filter @bklitui/ui check-types
pnpm --filter @bklitui/studio check-types提交PR前需执行:
bash
pnpm lint
pnpm --filter @bklitui/ui check-types
pnpm --filter @bklitui/studio check-typesscoped production build when touching studio/web
当修改studio/web时,执行限定范围的生产构建
Manual `/studio?chart=<slug>`:
- [ ] Enter animation
- [ ] Hover / legend sync
- [ ] Drag geometry sliders (no unnecessary remount)
- [ ] Canvas pan (space + drag) after enter — FPS near pie-chart baseline
- [ ] Pattern/gradient mode if supported
---
手动访问`/studio?chart=<slug>`验证:
- [ ] 入场动画正常
- [ ] 悬停/图例同步正常
- [ ] 拖动几何形状滑块(无不必要的重新挂载)
- [ ] 入场完成后画布平移(空格+拖动)—— FPS接近饼图基准
- [ ] 若支持图案/渐变模式,需验证该模式正常
---Chart status (bklit-ui)
图表状态(bklit-ui)
| Chart | Slug | Status |
|---|---|---|
| Pie | | ✅ Reference (#120) |
| Ring | | ✅ Aligned to checklist (context split, static paths, |
| Radar / Funnel / Choropleth | various | Partial — run checklist |
| Cartesian / scatter / live-line | various | ✅ #91 decimation + hover batching |
| Sankey | | |
| Gauge | | Low priority (single arc) |
| 图表 | Slug | 状态 |
|---|---|---|
| 饼图 | | ✅ 参考实现(#120) |
| 环形图 | | ✅ 符合检查清单(上下文拆分、静态路径、 |
| 雷达图/漏斗图/分级统计图 | 多种 | 部分完成 —— 执行检查清单 |
| 笛卡尔图/散点图/实时折线图 | 多种 | ✅ #91 降采样 + 悬停批处理 |
| 桑基图 | | 在链接描边上使用 |
| 仪表盘 | | 低优先级(仅单个圆弧) |
Key files
关键文件
| Area | Path |
|---|---|
| Enter-complete hook | |
| Pie reference | |
| Ring | |
| Pan isolation | |
| Registry | |
| 领域 | 路径 |
|---|---|
| 入场完成钩子 | |
| 饼图参考实现 | |
| 环形图 | |
| 平移隔离 | |
| 注册表 | |