Interpolation
interpolate and interpolateColor map a shared value
through a piecewise-linear curve and return a binding for an { animated }
style position. One value can then drive several properties, each over its
own range, and the mapping is evaluated on the Bevy side every frame.
Usage
import {
interpolate,
interpolateColor,
useSharedValue,
withTiming,
} from "bevy-react";
function Card() {
const t = useSharedValue(0);
return (
<node
onPointerEnter={() => {
t.value = withTiming(1, { duration: 200 });
}}
onPointerLeave={() => {
t.value = withTiming(0, { duration: 200 });
}}
style={{
width: 120,
height: 80,
transform: {
scale: { animated: interpolate(t, [0, 1], [1, 1.1]) },
},
backgroundColor: {
animated: interpolateColor(t, [0, 1], ["#7aa2f7", "#f7768e"]),
},
}}
/>
);
}The shared value runs from 0 to 1, the scale from 1 to 1.1 and the color
from blue to red. Setting the value directly (t.value = 0.5, from a slider
for example) moves every binding at once, with no driver at all.
interpolate
interpolate(value, input, output) returns a number binding:
inputlists readings of the shared value in ascending order, andoutputthe result at each of them, in the units of the position it binds: pixels for lengths, degrees for rotations (see Animated values).Between two neighbouring stops the result is linear. Use as many stops as you need:
translateY: { animated: interpolate( t, [0, 0.25, 0.5, 0.75, 1], [34, -34, 34, -34, 34], ), },Outside the input range the result clamps to the first or last output. There is no extrapolation option; add stops beyond the range where you want the curve to continue.
A repeated input stop makes a step:
input: [0, 0.5, 0.5, 1]withoutput: [0, 0, 1, 1]jumps from 0 to 1 at 0.5.Extra stops in the longer of the two lists are ignored. A single stop gives a constant.
Clamping makes staggering easy: give each item its own window of the same value, and it sits at an end of its range outside that window.
items.map((item, i) => (
<node
key={item.id}
style={{
width: 18,
height: {
animated: interpolate(t, [i * 0.16, i * 0.16 + 0.36], [10, 68]),
},
}}
/>
));interpolateColor
interpolateColor(value, input, colors) returns a color binding, for the
positions that take one: backgroundColor, borderColor, color, a
backgroundImage tint, gradient stop colors and color filter params.
colorsare hex strings:#rgb,#rrggbb, or#rrggbbaawith alpha. Other color syntaxes (rgb(), named colors,#rgba) are not understood; the binding is rejected with astyleBindingwarning and does nothing.- Colors are interpolated channel by channel in sRGB, alpha included.
- Stops, ordering and clamping work as for
interpolate.
With drivers
The bindings follow the shared value whatever moves it, so animate one progress value and map it per property. Because the curve clamps, a spring that overshoots past the last stop holds at the last output; extend the stops when the overshoot should show:
t.value = withSpring(1, { damping: 8 });
scale: { animated: interpolate(t, [0, 1, 2], [1, 1.1, 1.2]) },Writing the binding inline in render costs nothing extra: an unchanged binding compares equal and sends no update.
Limits
- Curves are piecewise linear only. Shape the timing with the driver's easing or spring instead.
interpolateColortakes hex colors only and interpolates in sRGB, which can pass through muddy midpoints between distant hues. Add an intermediate stop to steer it.- Bindings, interpolated or not, work in the base
styleonly.
The Animatable column of the style reference marks every property that accepts a binding.
bevy-react