[Perf] Axis tick labels are keyed by value, so relative ticks on a rolling window recreate every label
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 半日
- 初心者へのやさしさ
- 45/100
- issue の種類
- 機能追加
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 技術スタック
- d3, typescript
調査の方向性
The label key is built in scene.ts around line 1882 and written to data-ts-key in svg-renderer.ts, then matched by reconcile.ts around lines 344-345. Start by running the repro in packages/charts-core/test-repro/10-rolling-windows.test.ts to see the 4 new label nodes. Done means that test passes with a tick-index key, and that the default 'value' behaviour and the existing tests still pass.
索引モデルが issue の本文から書いたものです。
説明
Version: @tanstack/charts 1.1.0 (57774e1).
Problem
A rolling line chart (path: { update: 'rolling' }) with x ticks relative to the newest sample (ticks.values: "now - 30 s", "now - 20 s", ...) gets new tick values every step. Tick labels are keyed by value, so every label node is removed and re-created each step.
With default "nice" ticks the values persist, so this only shows with relative or per-step tick values.
Why
- Label key is the tick value:
scene.ts:1882. - The renderer writes it to
data-ts-key(svg-renderer.ts:192) and the reconciler matches nodes by it (reconcile.ts:344-345). No match means remove and re-create. - No
tickLabelsoption changes the key (types.ts:391-405).
Repro
Save as packages/charts-core/src/repro.test.ts, run pnpm vitest run packages/charts-core/src/repro.test.ts.
import { expect, it, vi } from 'vitest'
import { scaleLinear, scaleUtc } from 'd3-scale'
import { lineY } from './line'
import { motion } from './motion'
import { createChartScene, defineChart } from './scene'
const T0 = Date.UTC(2026, 0, 1)
const scene = (start: number) => {
const rows = Array.from({ length: 40 }, (_, i) => ({
id: `r${start + i}`, time: new Date(T0 + (start + i) * 1000), value: 50 + 20 * Math.sin(i / 2),
}))
const end = rows[39]!.time.getTime()
return createChartScene(defineChart({
motion: { path: { update: 'rolling', x: 'shift' }, transition: { type: 'tween', duration: 100 } },
marks: [lineY(rows, { id: 's', x: 'time', y: 'value', key: 'id' })],
scales: {
x: {
scale: scaleUtc().domain([rows[2]!.time, rows[39]!.time]),
axis: { ticks: { values: [30, 20, 10, 0].map((s) => new Date(end - s * 1000)) } },
},
y: { scale: scaleLinear().domain([0, 100]) },
},
clip: true,
}), { width: 300, height: 200 })
}
it('x tick label nodes are reused across a one-step rolling update', () => {
vi.spyOn(window, 'requestAnimationFrame').mockImplementation(() => 1)
const container = document.createElement('div')
const surface = motion({ initial: false }).mount(container, () => {})
const labels = () => [...container.querySelectorAll('text[data-ts-key^="x-tick-label:"]')]
surface.render(scene(0), { ariaLabel: 'rolling' })
const before = labels()
surface.render(scene(1), { ariaLabel: 'rolling' })
expect(labels().filter((node) => !before.includes(node))).toHaveLength(0)
})
Output: AssertionError: expected [ SVGElement{ …(2) }, …(3) ] to have a length of +0 but got 4. Without values the same test passes.
Proposed
tickLabels.key: 'value' | 'index' (default 'value'), switching the key at scene.ts:1882 to the tick index, so a fixed set of label nodes is reused and only text and position update.
Downstream measurement (bklit migration, Chrome, 10 s rolling line with relative x ticks): custom x labels keyed by slot index cut element additions from about 500 to 1.
- 主要言語
- TypeScript
- スター
- 819
- フォーク
- 49
- 平均マージ
- 12時間 9分
- マージ済み PR(30日)
- 6
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
TanStack/charts のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
Renderer treats a sub-pixel width difference as a resize, which cancels the `motion()` entranceオープン
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
TanStack/charts#182 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
brushX with `values` can shorten the selection range when it’s dragged to the plot edge対応中かも @andersk が 6 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 42/100
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 57/100
メンテナーはふだん 1 日以内に返信
TanStack/charts の issue をすべて見る
似ている issue
-
難易度 1/5 1〜3時間 初心者へのやさしさ 70/100
siyuan-note/siyuan#20517 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
NaturalIntelligence/fast-xml-parser#890 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
zsviczian/obsidian-excalidraw-plugin#3000 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
pnpm/get.pnpm.io#68 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
nuxt-modules/better-auth#578 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信