Анимационная подсистема Three.js основана на идее разделения анимации на независимые каналы данных — треки анимации. Каждый трек описывает изменение одного конкретного свойства объекта во времени.
Треки объединяются в объект AnimationClip, который представляет завершённую анимационную последовательность. Внутри клипа может находиться любое количество треков, управляющих различными параметрами сцены: положением объектов, вращением, масштабом, цветом материалов, морф-таргетами и другими характеристиками.
Основным базовым классом всех треков является KeyframeTrack. Он определяет структуру данных для хранения ключевых кадров и алгоритмы интерполяции между ними.
Класс KeyframeTrack описывает анимацию одного свойства объекта через набор ключевых кадров.
Ключевой кадр содержит:
В промежутках между ключевыми кадрами значение вычисляется интерполяцией.
Основные параметры конструктора:
new THREE.KeyframeTrack(name, times, values, interpolation)
Параметры:
Пример создания трека положения:
const times = [0, 1, 2];
const values = [
0, 0, 0,
5, 0, 0,
10, 0, 0
];
const track = new THREE.VectorKeyframeTrack(
'.position',
times,
values
);
Здесь:
(0,0,0)(5,0,0)(10,0,0)Поле name указывает путь к свойству объекта, которое будет анимироваться.
Структура записи:
nodeName.property
или
.property
Примеры:
.position
.rotation
.scale
.material.opacity
.bones[Arm].rotation
.morphTargetInfluences[0]
Механизм связывания называется PropertyBinding. Он позволяет системе анимации автоматически находить соответствующее свойство в объекте сцены.
Массив times хранит временные точки:
[0, 1, 2, 3]
Каждое число — момент времени в секундах.
Массив values содержит данные, соответствующие каждому времени.
Тип данных зависит от вида трека:
| Тип трека | Размер значения |
|---|---|
| Scalar | 1 |
| Vector3 | 3 |
| Quaternion | 4 |
| Color | 3 |
| Boolean | 1 |
| String | 1 |
Пример для Vector3:
values = [
x1, y1, z1,
x2, y2, z2,
x3, y3, z3
]
KeyframeTrack поддерживает несколько типов интерполяции.
Самый распространённый режим.
THREE.InterpolateLinear
Значения плавно изменяются между ключевыми кадрами.
Значение остаётся постоянным до следующего ключевого кадра.
THREE.InterpolateDiscrete
Используется для:
Более плавное изменение значений.
THREE.InterpolateSmooth
Применяется для сложных анимаций движения.
Three.js содержит несколько специализированных классов треков. Каждый из них оптимизирован под конкретный тип данных.
Используется для анимации одного числового параметра.
Примеры:
Пример:
const times = [0, 1, 2];
const values = [1, 0.5, 0];
const track = new THREE.NumberKeyframeTrack(
'.material.opacity',
times,
values
);
Анимация делает материал постепенно прозрачным.
Применяется для свойств, представленных векторами.
Наиболее частые случаи:
Пример:
const times = [0, 1, 2];
const values = [
0, 0, 0,
3, 5, 0,
6, 5, 2
];
const track = new THREE.VectorKeyframeTrack(
'.position',
times,
values
);
Каждый ключевой кадр содержит координаты Vector3.
Используется для анимации вращения.
В Three.js вращение часто представляется кватернионами, поскольку они:
Пример:
const times = [0, 1];
const values = [
0, 0, 0, 1,
0, 0.707, 0, 0.707
];
const track = new THREE.QuaternionKeyframeTrack(
'.quaternion',
times,
values
);
Интерполяция выполняется методом slerp (spherical linear interpolation).
Анимирует цвет.
Пример применения:
Пример:
const times = [0, 1, 2];
const values = [
1, 0, 0,
0, 1, 0,
0, 0, 1
];
const track = new THREE.ColorKeyframeTrack(
'.material.color',
times,
values
);
Цвет меняется:
красный → зелёный → синий
Используется для логических значений.
Пример:
const times = [0, 2];
const values = [true, false];
const track = new THREE.BooleanKeyframeTrack(
'.visible',
times,
values
);
Интерполяция всегда дискретная.
Анимирует строковые значения.
Используется редко, но может применяться для:
Пример:
const times = [0, 1];
const values = ["idle", "run"];
const track = new THREE.StringKeyframeTrack(
'.state',
times,
values
);
Один трек управляет только одним свойством. Для создания полноценной анимации несколько треков объединяются в AnimationClip.
Пример:
const positionTrack = new THREE.VectorKeyframeTrack(
'.position',
[0, 1, 2],
[
0,0,0,
5,0,0,
10,0,0
]
);
const rotationTrack = new THREE.QuaternionKeyframeTrack(
'.quaternion',
[0, 2],
[
0,0,0,1,
0,0.707,0,0.707
]
);
const clip = new THREE.AnimationClip(
'MoveAndRotate',
2,
[positionTrack, rotationTrack]
);
В этом клипе:
Для корректной работы трек должен соответствовать ряду требований:
1. Время должно быть отсортировано
0 < 1 < 2 < 3
2. Количество значений должно соответствовать размерности
Например для Vector3:
values.length = times.length × 3
3. Все значения должны быть одного типа
Смешивание типов недопустимо.
Позволяет изменить тип интерполяции.
track.setInterpolation(THREE.InterpolateLinear);
Возвращает текущий тип интерполяции.
track.getInterpolation();
Удаляет избыточные ключевые кадры.
Например, если два соседних кадра имеют одинаковые значения.
track.optimize();
Это уменьшает объём данных и повышает производительность.
Проверяет корректность структуры трека.
track.validate();
Проверяются:
Создаёт копию трека.
const copy = track.clone();
Для воспроизведения треков применяется AnimationMixer.
Пример:
const mixer = new THREE.AnimationMixer(mesh);
const action = mixer.clipAction(clip);
action.play();
В игровом цикле:
mixer.update(delta);
delta — время между кадрами.
При создании сложных анимаций количество ключевых кадров может быть очень большим. Для оптимизации используются:
1. Сжатие ключевых кадров
Удаление повторяющихся значений.
2. Минимизация треков
Анимировать только те свойства, которые действительно изменяются.
3. Использование Quaternion вместо Euler
Позволяет избежать ошибок интерполяции вращения.
4. Группировка треков
Один клип может содержать десятки треков, но система анимации эффективно обрабатывает их пакетно.
Треки KeyframeTrack используются для:
Система треков является фундаментом всей анимационной архитектуры Three.js и обеспечивает универсальный механизм описания изменений свойств объектов во времени.