Custom easing with Interpolator
Overview
Interpolator<T> is the Luau interface for custom interpolation behavior in Rive; its C++ runtime implementation is named ScriptedInterpolator. This lesson follows a quadratic ease-in from its input factor to the final blended value. For the callback signatures without the walkthrough, use the Interpolation API reference.
If you are choosing where a script belongs, start with Rive script types. A custom interpolator handles easing; it does not replace a Node script's drawing or a Converter's data-binding transformation.
This protocol is tracked against released Web 2.42.1 -> C++
runtime-v0.1.384, with source pins documented in
Runtime Compatibility Baseline.
Use it when linear interpolation is not enough and you need script-defined easing at the interpolation level. Editor availability must be checked separately: runtime support alone does not prove that your editor exposes an attachment workflow.
Follow the value through the easing curve
The template below clamps the input factor to the range 0–1 and squares it. Squaring makes the early part of the transition progress more slowly. It then blends from 10 to 30 using that remapped factor:
| Input factor | Squared factor | Blended value |
|---|---|---|
| 0 | 0 | 10 |
| 0.25 | 0.0625 | 11.25 |
| 0.5 | 0.25 | 15 |
| 0.75 | 0.5625 | 21.25 |
| 1 | 1 | 30 |
At the halfway point, linear interpolation would produce 20. This ease-in produces 15, then catches up to the same endpoint. In the template, transform remaps the factor and transformValue explicitly calls it before blending the two values. Use the exercise near the end of this lesson to check that calculation.
Type Shape
export type Interpolator<T> = {
init: ((self: T, context: Context) -> boolean)?,
transform: ((self: T, factor: number) -> number)?,
transformValue: ((self: T, valueFrom: number, valueTo: number, factor: number) -> number)?,
} & T
Runtime callback behavior
The public Interpolator interface lists both callbacks as required. The accepted runtime supplies fallbacks if either is absent; the template implements both.
transform(self, factor) -> numbertransformValue(self, valueFrom, valueTo, factor) -> number
Runtime fallback behavior
If a method is omitted or errors, runtime falls back to standard linear behavior.
- Missing/failed
transform-> returns originalfactor - Missing/failed
transformValue-> usesfrom + (to - from) * factor
Template
export type MyInterpolator = {
strength: Input<number>,
}
function transform(self: MyInterpolator, factor: number): number
local t = math.max(0, math.min(1, factor))
return t * t
end
function transformValue(self: MyInterpolator, valueFrom: number, valueTo: number, factor: number): number
local t = transform(self, factor)
return valueFrom + (valueTo - valueFrom) * t
end
return function(): Interpolator<MyInterpolator>
return {
transform = transform,
transformValue = transformValue,
strength = 1,
}
end
Exercise 1: Build a Quadratic Ease-In Mapper ⭐⭐
Premise
You are implementing interpolation math that should start slow and accelerate.
Starter Code
local function transform(factor: number): number
-- TODO: clamp to [0, 1], then return quadratic ease-in
return factor
end
local function transformValue(valueFrom: number, valueTo: number, factor: number): number
-- TODO: map transform(factor) across [valueFrom, valueTo]
return valueFrom
end
local result = transformValue(10, 30, 0.5)
print(string.format("ANSWER: %.1f", result))
Expected output
ANSWER: 15.0
Verify Your Answer
Knowledge Check
Next Steps
- Review the Interpolation API Reference
- Continue to Util Protocol
- Verify status in Runtime Compatibility Baseline
- Need a refresher? Review Quick Reference