本页还没有译文
本页 33 段还没译成한국어,下面显示的是英文原文。Dynamic Data and Animation
还没翻译译自英文(tanstack.com)本页 33 段都还没译
Definition identity is the application update boundary. A framework memo captures the current data and options; Charts rebuilds the scene when that definition changes or when the chart surface changes size.
React
import { scaleBand } from '@tanstack/charts/scales/band'
import { scaleLinear } from '@tanstack/charts/scales/linear'
function RankingChart({ rows, metric, accent }: Props) {
const definition = useMemo(() => {
const ranked = rows
.map((row) => ({ label: row.label, value: row[metric] }))
.sort((left, right) => right.value - left.value)
return defineChart({
svgAnimation: { duration: 280, easing: 'ease-out' },
chart: ({ width }) => ({
marks: [
barX(ranked, {
x: 'value',
y: 'label',
fill: accent,
}),
],
scales: {
x: {
scale: scaleLinear,
nice: true,
axis: { ticks: { count: width < 420 ? 4 : 7 } },
},
y: {
scale: () => scaleBand<string>().padding(0.1),
},
},
}),
})
}, [rows, metric, accent])
return <Chart definition={definition} ariaLabel="Revenue ranking" />
}Use the framework's native equivalent: computed, createMemo, $derived,
Angular computed, or Octane useMemo.
Vanilla
host.update({
...options,
definition: createRankingDefinition(nextRows, nextMetric, nextAccent),
})Stable keys
Built-in marks first use an explicit key, then a unique datum.id, then a
unique nested datum.data.id. Marks can also infer identity from semantic
positional channels:
barX(rows, {
x: 'value',
y: 'label',
})Here barX uses the unique y value when rows have no id. barY uses x;
lineY and areaY use x; areaX uses y; rects and cells use their x/y
interval tuple. Dots and text try x, then y, then their x/y tuple. Inference is
scoped to each group and falls back to array position when a candidate is
incomplete or duplicated. Development builds warn once for each affected mark
instance.
Supply key when the inferred value is not the entity's identity or can
change independently of it. Stable identity preserves surviving SVG elements,
focused points, and transition continuity.
Lightweight SVG tweening
svgAnimation accepts true or:
duration: milliseconds;easing:linear,ease,ease-in,ease-out,ease-in-out, or a function from normalized progress to normalized progress;respectReducedMotion: defaults totrue;resize: defaults tofalse, so responsive relayout does not repeatedly restart animation.
Numeric geometry and compatible path data interpolate. Entering and exiting nodes reconcile by key. If an update interrupts a transition, it begins from the geometry currently painted on screen.
Static SVG, server rendering, and createChartScene do not include animation.
Use this path when a small default-SVG tween is enough. It has no spring solver, definition-local timing cascade, entrance choreography, or retained velocity.
Optional tween and spring motion
Use motion() when animation quality is part of the chart contract:
import { scaleUtc } from 'd3-scale'
import { motion } from '@tanstack/charts/motion'
import { stagger } from '@tanstack/charts/motion/definition'
import { mountChartRenderer } from '@tanstack/charts/renderer'
import { scaleLinear } from '@tanstack/charts/scales/linear'
const definition = defineChart({
motion: {
path: 'morph',
...stagger({ each: 35, roles: 'line', by: 'series' }),
},
marks: [
lineY(rows, {
x: 'date',
y: 'actual',
key: 'id',
}),
lineY(rows, {
x: 'date',
y: 'forecast',
key: 'id',
motion: { transition: { type: 'spring', mass: 1.25 } },
}),
],
scales: {
x: { scale: scaleUtc },
y: { scale: scaleLinear },
},
})
const host = mountChartRenderer(container, {
definition,
renderer: motion({
transition: { type: 'spring', stiffness: 170, damping: 18, mass: 1 },
}),
width: 640,
height: 360,
ariaLabel: 'Actual and forecast revenue',
})Each host has one animation owner. The default SVG renderer uses svgAnimation.
When motion() is the renderer, it ignores svgAnimation and uses motion
declarations from the definition. A motion declaration configures the motion
renderer; it does not select it.
Motion declarations can live on the chart, a mark, an axis, its ticks, tick
labels, or axis label. A callback can specialize enter, update, and exit
by series or datum:
barY(rows, {
x: 'month',
y: 'revenue',
key: 'id',
motion(context) {
if (context.phase === 'enter') {
return { delay: context.datumIndex * 35 }
}
if (context.datum?.status === 'forecast') {
return { transition: { type: 'tween', duration: 240 } }
}
},
})Same-type partial transitions inherit omitted properties. Springs use physical
stiffness, damping, and mass; duration is not a spring parameter. Rapid
retargeting preserves the currently painted value and velocity. Keyed
interaction points move with the presentation geometry rather than jumping to
the next scene.
A crosshair is also keyed focus presentation. With the motion renderer, its
rules, bands, labels, and marker retain DOM identity and spring velocity while
focus retargets. Default SVG, Canvas, and native surfaces paint the same guide
at its current target without importing the browser motion runtime.
stagger() contributes only a context-aware delay, so it composes with
transition and path fields through normal object spread. Spring updates always
retarget immediately; an update delay is ignored so incoming momentum cannot
freeze. Use delays for spring enter/exit choreography or any tween phase.
The renderer grows entering Cartesian bars, lines, and areas from their semantic baseline; grows radial paths from the polar center; sweeps arcs through their authored angle; staggers bar entrances; morphs compatible numeric SVG geometry; and keeps removed keys painted through their exit transition. Authored delay replaces automatic staggering for that target.
motion() respects reduced motion and does not animate resize-only updates by
default. It adopts server-rendered SVG without replaying entrance motion by
default; pass initial: 'always' to replay entrance motion after hydration.
Static SVG and Canvas accept the same definitions but paint the final state.
See the Motion reference for the complete cascade, types, focus-state transitions, compatibility limits, and standalone spring sampler.
See Themes and Motion examples for complete cards that separate keyed chart motion from controls, labels, and palette CSS.
Streaming
For high-rate data:
- Keep source history outside the chart if the product needs it.
- Capture a bounded visible window or encoded representation.
- Preserve keys for rows that survive the roll.
- Keep viewport state controlled.
- Coalesce upstream work when only the latest state matters.
For a scrolling trace, keep enough overscan before the visible x-domain to
cover the largest expected update batch, enable clip, and use a rolling path
contract:
const definition = defineChart({
motion: {
path: {
update: 'rolling',
x: 'shift',
y: 'reproject',
fallback: 'snap',
},
transition: { type: 'tween', duration: sampleInterval, easing: 'linear' },
},
marks,
scales: {
x: null,
y: null,
},
})The keyed retained window moves as one affine path. y: 'reproject' keeps that
motion valid while a continuous y-domain changes. A failed rolling invariant
snaps instead of occasionally becoming a different interpolation. Set
fallback: 'morph' only when path interpolation is intentional. A valid update
that arrives during another roll composes from the transform currently painted
on screen.
Keep viewport.translate at zero on both the previous and target scene during
a rolling update. A nonzero transient viewport translation makes the rolling
contract fail and uses its configured fallback. Commit the viewport domain and
reset the translation before applying the next live-data window. Keep plot
margins fixed and prefer linear segments so appending a sample cannot recompute
a visible curve tangent.
The final definition passed to host.update is applied synchronously.