Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
<= Предыдущая статья ExtendScript Работа с композициями
Привет.
В предыдущей статье мы сделали основу модели для построения титров на сцене After Effects. Мы добавляем в проект сцену, или несколько сцен. Теперь нам надо добавить на сцену сами титры. Для того чтобы добавить титры, следует создать в макете AE модели, которые послужат нам для копирования.
Заходим в проект, где уже создана композиция ModelScene_1x1. В той же папке 1x1 создаем две композиции. Одну назовем ModelTitre_simple_1x1, другую ModelTitre_double_1x1.
Начнем с композиции ModelTitre_simple_1x1. Добавим ее в композицию ModelScene_1x1.
В самой ModelTitre_simple_1x1 мы создадим текстовое поле. Назовем его reference_text.
Нам надо задать анимацию нашему титру. Можно сделать это скриптом, но мы не можем предугадать какую анимацию захочет создать моушен-дизайнер. Тем более для такого рода задач и предназначен After Effects, так и оставим это ему. Наша задача привязать запуск анимации к точке входа титра на сцене, и ее завершение к точке выхода. Ключевыми кадрами это решить несколько затруднительно. На помощь нам придет Expression, язык схожий с Javascript, который интерпретируется во время рендера и возвращает в каждом кадре текущее значение свойства, в котором оно написано. Проще понять на примере. Поэтому раскрываем наш слой reference_text, В нем раскрываем группу свойств Transform, и выделяем свойство Position.
Далее переходим в меню Animation > Add Expression. У свойства Position появится поле Expression и в нем дефолтный код, просто возвращающий текущее значение.
Поменяем этот код на следующий
var width = Math.round(thisLayer.sourceRectAtTime().width);
var padding = 20;
var hideX = -width - padding;
var showX = padding;
var posY = transform.position[1];
var animationTime = 0.5;
var timeIn = comp("ModelScene_1x1")
.layer(thisComp.name)
.inPoint;
var timeOut = comp("ModelScene_1x1")
.layer(thisComp.name)
.outPoint;
if (time <= animationTime) {
easeOut(
time,
0,
animationTime,
[hideX, posY],
[showX, posY]
);
} else {
easeOut(
time,
timeOut - timeIn - animationTime,
timeOut - timeIn,
[showX, posY],
[hideX, posY]
);
}
Давайте посмотрим, что тут у нас происходит. В начале кода мы объявляем несколько переменных. Во первых мы находим ширину текстового поля. Для этого мы используем глобальную переменную thisLayer, указывающую на этот слой,и ее метод sourceRectAtTime, который возвращает нам прямоугольник текста в текущем кадре.
thisLayer.sourceRectAtTime().width
Далее определяем отступ титра от левого края сцены. Высчитываем начальное и конечное положение титров. Когда титры скрыты, их позиция минус ширина текста и еще минус отступ, на сцене титры должны стоять на расстоянии отступа от левого края.
var hideX = -width - padding;
var showX = padding;
Положение титров по оси Y фиксированное, и определяется текущим положением слоя
var posY = transform.position[1];
Далее мы указываем продолжительность анимации в секундах, и находим время появления композиции на сцене и время ее завершения. Это нам необходимо для того, чтобы высчитать время для финальной анимации.
var animationTime = 0.5;
var timeIn = comp("ModelScene_1x1")
.layer(thisComp.name)
.inPoint;
var timeOut = comp("ModelScene_1x1")
.layer(thisComp.name)
.outPoint;
Находя время мы обращаемся к композиции сцены по ее имени, ModelScene_1x1, другого способа обратиться к родительскому элементу нет. Находим на сцене слой с таким же именем, как и имя текущей композиции в проекте, thisComp.name. Затем сохраняем свойства inPoint и outPoint нашего слоя с титрами.
Подготовка завершена, теперь осталось выполнить саму анимацию. Сначала мы проверяем текущее время композиции, оно отсчитывается от 0. Если время меньше или равно animationTime, то логично предположить, что это время стартовой анимации.
if (time <= animationTime) {
easeOut(
time,
0,
animationTime,
[hideX, posY],
[showX, posY]
);
}
Метод easeOut, возвращающий текущее положение слоя в зависимости от времени, принимает 5 обязательных аргументов.
time - время внутри данной композиции
startTime - время начала анимации, метод будет работать только если time >= startTime
endTime - время завершения анимации
startPosition - значение анимируемого свойства в начале анимации
endPosition - значение свойства по завершении анимации
Свойство position имеет два значения, X и Y. Оба значение хранятся в виде массива, где первый элемент, это значение X, а второй - Y.
Ну, а если время стартовой анимации прошло, то мы запускаем завершающую анимацию
easeOut(
time,
timeOut - timeIn - animationTime,
timeOut - timeIn,
[showX, posY],
[hideX, posY]
);
Продолжительность титра - его точка выхода на сцене минус точка входа
timeOut - timeIn
Соответственно время старта анимации равно этому значению минус animationTime
timeOut - timeIn - animationTime
Можете проверить анимацию, как внутри композиции с титром, так и на сцене ModelScene_1x1. Переместите титр на временной шкале, сократите его длительность, анимация подстроится под вашу настройку.
Давайте теперь сделаем то же со вторым титром, ModelTiter_double_1x1. Выложим его на сцену и войдем в него. Тут анимация будет несколько сложнее, мы будем анимировать две строки независимо друг от друга. И, как ни странно, для этого нам понадобится три текстовых слоя. Один мы назовем reference_text, два других strin_1 и string_2
Кликаем по слою reference_text правой клавишей и выбираем в контекстном меню пункт Guide Layer.
Слой становится техническим, и при рендере отображаться не будет. Нам он потребуется только для хранения текста, который будут читать и отображать слои string_1 и string_2. Для чего нам это нужно? Мы не знаем заранее сложность самого титра и какие слои в него вложены. Поэтому возьмем за правило, что в каждом титре есть слой с именем reference_text. Наш скрипт будет именно в этот слой копировать распарсенный текст, а все остальное мы оставим на волю макета.
Чтобы отобразить в строке нужную часть текста, нам снова поможет Expression. Выделяем свойство sourceText слоя string_1 и выбираем в меню Animation > Add Expression
Заменяем выражение на следующее
var refText = thisComp.layer("reference_text")
.text.sourceText.split("\r");
var stringID = parseInt(thisLayer.name.split("_")[1]);
refText[stringID - 1]
Мы разбиваем текст из слоя reference_text по разделителю перенос. Обратите внимание, что тут перенос обозначается как \r. Далее можно было бы просто вернуть refText[0], но чтобы код был универсален для обеих строк, мы выделим из имени слоя его id, и вернем элемент массива refText соответствующий этому id. Теперь мы можем скопировать это же выражение и в свойство sourceText слоя string_2. Таким образом текстом string_1 будет первая строка reference_text, а string_2 - вторая.
Теперь анимируем наши строки. Анимация будет почти в точности повторять анимацию титра simple, с той лишь разницей, что мы добавим в нее небольшую задержку. Вторая строка будет появляться с учетом этой задержки, а первая исчезать так же с ее учетом.
Добавляем свойству Position слоя string_1Expression и копируем туда код из текстового поля композиции ModelTitre_simple_1x1. Дополняем код объявлением переменной delay.
var delay = 0.3;
И вычитаем ее значение из финала анимации (первая строка будет уезжать на 0.3 секунды раньше)
easeOut(time,
timeOut - timeIn - animationTime - delay,
timeOut - timeIn - delay,
[showX, posY],
[hideX, posY]
);
Решить, как поступить с переменной delay в коде второй строки, оставляю вам для самостоятельной работы.
Теперь у нас есть макеты двух видов титров и все готово для того, чтобы выложить их на сцену. Но о том, как это сделать, мы поговорим в следующий раз.
Все Expressions из этой статьи вы можете скачать тут
Документация по Expression тут
На сегодня все.
<= Предыдущая статья ExtendScript Работа с композициями