bklit-studio-chart-performance

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Studio 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
displayState
on every slider tick and on legend/slice hover. Trace:
  • Does hover live in the same context as data, scales, and animation config?
  • Does the preview recreate children (
    data.map
    , pattern defs, motion props) every render?
  • Does the chart remount unnecessarily (
    key
    tied to motion signature vs manual replay)?
Pattern: Split context like cartesian / pie charts — stable slice (data, geometry, animation config) vs hover slice (
hoveredIndex
, tooltip). Consumers that don't need hover use only the stable hook (
usePieStable
,
useRingStable
,
useChartStable
, …).
Studio pan: Wrap chart render in
StudioChartRender
(
packages/studio/src/components/studio-chart-render.tsx
) so camera pan / FPS counter parent updates skip the chart tree when render props are unchanged.

Studio会在每次滑块刻度变化、图例/切片悬停时更新
displayState
。排查方向:
  • 悬停逻辑是否与数据、比例尺、动画配置处于同一上下文
  • 预览是否会在每次渲染时重新创建子组件
    data.map
    、图案定义、motion属性)?
  • 图表是否会不必要地重新挂载
    key
    绑定到motion签名而非手动重放)?
模式: 像笛卡尔图/饼图那样拆分上下文 —— 稳定切片(数据、几何形状、动画配置) vs 悬停切片
hoveredIndex
、提示框)。不需要悬停功能的消费者仅使用稳定钩子(
usePieStable
useRingStable
useChartStable
等)。
Studio平移: 将图表渲染包裹在
StudioChartRender
packages/studio/src/components/studio-chart-render.tsx
)中,这样相机平移/FPS计数器父组件更新时,若渲染属性未变化,就会跳过图表树的更新。

2. Treat SVG path
d
animation as expensive

2. 视SVG路径
d
动画为高开销操作

Animating
d
with Motion /
useTransform
+ d3 arc (or similar) runs layout + paint every frame, per series.
PreferAvoid
transform
/
opacity
for hover (compositor-friendly)
Continuous
d
morphing after enter is done
Static
d
once enter finishes
Keeping Motion subscriptions on
d
for the chart's lifetime
Enter animation only, then static pathsRe-running enter path math on unrelated prop changes
Pattern:
useMountProgress
for enter → when progress ≥ 1 (
useEnterComplete
), render static paths and only animate hover with
x
/
y
/
opacity
/
scale
on a
motion.g
wrapper (not per-path
scale
on
motion.path
).
Shared hook:
packages/ui/src/charts/use-enter-complete.ts

使用Motion /
useTransform
+ d3 arc(或类似工具)对
d
属性进行动画,会在每一帧对每个系列执行布局+绘制操作。
推荐方案避免操作
使用
transform
/
opacity
实现悬停(合成器友好)
入场完成后持续对
d
属性进行变形动画
入场完成后使用静态
d
属性
在图表生命周期内保持对
d
属性的Motion订阅
仅保留入场动画,之后使用静态路径在无关属性变化时重新执行入场路径计算
模式: 使用
useMountProgress
处理入场动画 → 当进度≥1时(通过
useEnterComplete
判断),渲染静态路径,并仅在**
motion.g
**容器上使用
x
/
y
/
opacity
/
scale
实现悬停动画(而非在每个
motion.path
上单独设置
scale
)。
共享钩子:
packages/ui/src/charts/use-enter-complete.ts

3. 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
    hoveredIndex
    + stable
    setHoveredIndex
    (
    useCallback
    in chart shell).
  • Match
    isLoaded
    to ring/cartesian:
    useEffect
    + timeout, not a lazy
    useState
    initializer.
Reference:
pie-context.tsx
,
ring-context.tsx
,
chart-context.tsx
,
PieChartCore
/
RingChartCore
useMemo
on provider value.

未记忆化的提供者值会强制所有子组件在每次父组件渲染时重新协调。
  • 使用显式依赖项(数据、圆弧/半径、尺寸、回调)记忆化稳定上下文对象
  • 基于
    hoveredIndex
    和稳定的
    setHoveredIndex
    (图表外壳中的
    useCallback
    )记忆化悬停上下文
  • 匹配环形图/笛卡尔图的**
    isLoaded
    **逻辑:使用
    useEffect
    + 超时,而非惰性
    useState
    初始化器。
参考实现:
pie-context.tsx
ring-context.tsx
chart-context.tsx
PieChartCore
/
RingChartCore
中对提供者值使用
useMemo

4. Studio preview–specific wins

4. Studio预览专属优化技巧

Chart-agnostic; apply in
packages/studio/src/components/charts/*-studio*.tsx
:
WinHow
Conditional defsOnly pass
patternDefs
/ gradients when a series uses patterns
Memo derived dataColored/mapped data arrays; slice/series lists (
useMemo
, deps:
dataSeed
+ design fields that affect color)
Memo motion enterDon't call
getStudioMotionEnterProps
inline;
useMemo
with motion-only deps (not full
state
)
Memo legend hover
{ hoveredIndex, setHoveredIndex }
in
useMemo
— already in
studio-legend-hover.tsx
Memo chart body
memo()
wrapper; pass primitives (
chartKey
,
chartSize
,
data
) not whole
ctx
so pan/shell re-renders skip rebuild
Disable glow in Studio
showGlow={false}
on series components
Reference:
pie-studio-preview.tsx
,
ring-studio-preview.tsx

与图表类型无关;可在
packages/studio/src/components/charts/*-studio*.tsx
中应用:
优化点实现方式
条件式定义仅当系列使用图案时才传递
patternDefs
/ 渐变
记忆化衍生数据着色/映射后的数数组、切片/系列列表(使用
useMemo
,依赖项:
dataSeed
+ 影响颜色的设计字段)
记忆化motion入场属性不要内联调用
getStudioMotionEnterProps
;使用仅与motion相关的依赖项(而非完整
state
)通过
useMemo
处理
记忆化图例悬停
useMemo
中处理
{ hoveredIndex, setHoveredIndex }
——
studio-legend-hover.tsx
中已实现
记忆化图表主体使用
memo()
包装;传递原始类型值
chartKey
chartSize
data
)而非完整
ctx
,这样平移/外壳重新渲染时会跳过重建
在Studio中禁用发光效果在系列组件上设置
showGlow={false}
参考实现:
pie-studio-preview.tsx
ring-studio-preview.tsx

5. 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):
CheckSlow chart often hasFast chart often has
ShellInline render, extra defs
StudioChartShell
+ conditional patterns
Series countMany animated pathsFewer paths or simpler geometry
HoverContext + full tree re-renderStable subscribers; hover on
motion.g
/ translate
EnterPath
d
wipe per series
Static
d
after enter; transform-only hover
PanChart tree rebuilds every frame
StudioChartRender
memo boundary

将卡顿的图表与同一编辑器中运行流畅的图表(通常是饼图)进行对比:
检查项卡顿图表通常存在的问题流畅图表通常具备的特征
外壳内联渲染、冗余定义
StudioChartShell
+ 条件式图案
系列数量大量带动画的路径路径更少或几何形状更简单
悬停上下文触发整树重新渲染稳定的订阅者;在
motion.g
/ 平移上实现悬停
入场动画每个系列都有路径
d
擦除动画
入场后使用静态
d
;仅通过变换实现悬停
平移图表树每帧都重建
StudioChartRender
记忆化边界

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-types

scoped 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)

ChartSlugStatus
Pie
pie-chart
✅ Reference (#120)
Ring
ring-chart
✅ Aligned to checklist (context split, static paths,
StudioChartRender
, preview memo)
Radar / Funnel / ChoroplethvariousPartial — run checklist
Cartesian / scatter / live-linevarious✅ #91 decimation + hover batching
Sankey
sankey-chart
useTransform
on link stroke — candidate for
useEnterComplete
Gauge
gauge-chart
Low priority (single arc)

图表Slug状态
饼图
pie-chart
✅ 参考实现(#120)
环形图
ring-chart
✅ 符合检查清单(上下文拆分、静态路径、
StudioChartRender
、预览记忆化)
雷达图/漏斗图/分级统计图多种部分完成 —— 执行检查清单
笛卡尔图/散点图/实时折线图多种✅ #91 降采样 + 悬停批处理
桑基图
sankey-chart
在链接描边上使用
useTransform
—— 适合应用
useEnterComplete
仪表盘
gauge-chart
低优先级(仅单个圆弧)

Key files

关键文件

AreaPath
Enter-complete hook
packages/ui/src/charts/use-enter-complete.ts
Pie reference
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
Pan isolation
packages/studio/src/components/studio-chart-render.tsx
Registry
packages/studio/src/lib/registry.tsx
领域路径
入场完成钩子
packages/ui/src/charts/use-enter-complete.ts
饼图参考实现
packages/ui/src/charts/pie-slice.tsx
,
pie-context.tsx
,
pie-studio-preview.tsx
环形图
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