animate
Одноразовый твин значения на кадровых часах хоста: интерполирует from → to за duration и
вызывает onUpdate с текущим значением каждый кадр. Он анимирует значения, а не объекты — значение
ты применяешь сам в onUpdate. Для бесконечного покадрового движения используй setLoop
(Глобалы хоста).
Обзор
const id = animate({
from: 0,
to: 1,
duration: 400, // миллисекунды
easing: easeOut,
onUpdate: v => { ghost.opacity = v },
onComplete: () => console.log('faded in'),
})Запуск твина
animate({
from: T, // начальное значение
to: T, // конечное значение — его форма выбирает интерполяцию (см. ниже)
duration: number, // МИЛЛИСЕКУНДЫ
onUpdate(val: T): void, // вызывается каждый кадр с интерполированным значением
onComplete?(): void, // вызывается один раз, после финального onUpdate
easing?: Easing, // отображает линейный прогресс 0..1; по умолчанию линейный
}): number // id анимации для stop/pause/resumeduration — миллисекунды (кадровый dt — секунды; длительности UI .animateTo() тоже в мс).
См. Соглашения.
easing получает сырой линейный прогресс 0..1 и возвращает сглаженный — см.
Функции сглаживания. onComplete срабатывает, когда прогресс достигает
1; твин, остановленный раньше, его не вызывает.
Виды значений
Форма to выбирает интерполяцию:
to |
Интерполяция | onUpdate получает |
|---|---|---|
number |
lerp | number |
массив длины 2 (как Vec2) |
покомпонентный lerp | Float32Array (переиспользуется) |
массив длины 3 (как Vec3) |
покомпонентный lerp | Float32Array (переиспользуется) |
массив длины 4 (как Quat) |
slerp кватерниона | Float32Array (переиспользуется) |
для массивных видов onUpdate получает один и тот же Float32Array каждый кадр — он
перезаписывается на месте. Не храни ссылку; копируй ([...v]), если нужно сохранить значение кадра.
массивы длины 4 всегда трактуются как кватернионы (slerp с переворотом полушария) — не анимируй RGBA-кортеж как массив длины 4.
строковые значения (цвета). Ветка цвета в исходнике — мёртвый код (сравнивает значение, а не тип),
поэтому строковый to проваливается в проверки длины массива и не даёт ничего полезного — NaN на
строках из 2/3/4 символов, полный no-op в остальных случаях. Исключение не бросается. Анимируй цвет,
твиня число 0..1 и смешивая два цвета сам в onUpdate.
Управление запущенным твином
stopAnimation(id: number): void // остановить навсегда — больше нет onUpdate, нет onComplete
pauseAnimation(id: number): void // заморозить прогресс
resumeAnimation(id: number): void // продолжить приостановленный твинanimateMat4 — твин матрицы трансформа
animateMat4({
from: Mat4Like, // Float32Array | number[], 16 элементов
to: Mat4Like,
duration: number, // миллисекунды
onUpdate(m: Float32Array): void,
onComplete?(): void,
easing?: Easing,
}): numberПоэлементный lerp матрицы дал бы скос; animateMat4 вместо этого раскладывает обе матрицы один раз
в момент вызова на позицию / поворот / масштаб, lerp'ит позицию и масштаб, slerp'ит поворот и
пересобирает каждый кадр. onUpdate получает переиспользуемый Float32Array из 16 элементов — то же
правило «не храни ссылку», что и у векторных видов.
Подводные камни
// ✗ duration в секундах — твин завершится меньше чем за кадр
animate({ from: 0, to: 100, duration: 0.5, onUpdate: v => { node.x = v } })
// ✓ миллисекунды
animate({ from: 0, to: 100, duration: 500, onUpdate: v => { node.x = v } })
// ✗ хранение vec-значения — все записи окажутся одним (финальным) массивом
animate({ from: [0, 0], to: [10, 10], duration: 300, onUpdate: v => path.push(v) })
// ✓ копируй значение кадра
animate({ from: [0, 0], to: [10, 10], duration: 300, onUpdate: v => path.push([...v]) })Смотрите также
- Функции сглаживания —
easeIn/easeOut/easeInOut,cubicBezier, свои функции. - Соглашения — время — где SDK использует секунды, а где миллисекунды.
- Глобалы хоста —
setLoopдля бесконечной покадровой анимации.