Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[Perf] Axis tick labels are keyed by value, so relative ticks on a rolling window recreate every label

オープン
#195 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 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
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

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

TanStack/charts のほかの issue

TanStack/charts の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。