After Effects arrays and strings
TOC
Это небольшой справочник, который я решила сделать для себя и всех, кто часто использует выражения при работе в Adobe After Effects. Поскольку выражения являются подмножеством JS, то многие возможности ускользают от пользователей After Effects, мало знакомых с программированием. Я решила пройтись по JS и протестировать совместимые функции и методы. Надеюсь этот справочник поможет вам успешнее использовать выражения в вашей работе и применять больше генеративных возможностей. Этот справочник будет уточняться и расширяться. Все, что здесь написано, проверено для версии CC 2014.
1. Массивы
Массив (объект Array) это объект, в котором сохранено некоторое количество других объектов, где каждому из них сопоставлен последовательный номер (индекс элемента). Элементы называются объектами, т.к. не имеют четкого типа. Вы можете смешивать в массиве значения разных типов (например и числовые и текстовые). Но за этим кроются некоторые подводные камни. Для простоты будем пока рассматривать одномерный массив вида:
[1, 2, 3, 5, 7, "eight", -10]
Операции с массивам перебором элементов в цикле это громоздко и медленно, давайте посмотрим, какие возможности нам предоставляет Java Script. Начнем с базовых арифметических операций. Для этого нам надо избавиться от текстового значения в примере выше, иначе мы получим сообщение об ошибке, т.к аримфетические операции не могут применяться к текстовым значениям.
Для нижеследующих примеров возьмем за исходный массив:
a = [1, 2, 3, 5, 7, 8, -10]
Я наверное опущу такие простые операции, как извлечение элемента массива вида b = a[3]
, когда в результате переменной b мы присваиваем значение третьего элемента. Не забывайте, что нумерация элементов массива начинается с нуля.
1.1 Сложение и вычитание массивов
b = a + 1
В данной операции правый операнд автоматически интерпретируется (type casting) как массив из одного элемента.
Таким образом единица добавится к нулевому элементу массива:
a + [1] => [2, 2, 3, 5, 7, 8, -10]
Отсюда легко догадаться каков будет результат следующей операции.
К первым трем элемента будет добавлено по единице:
b = a + [1, 1, 1] => [2, 3, 4, 5, 7, 8, -10]
1.2 Умножение и деление
Здесь все работает немного по-другому, и операция умножения или деления выполняется для всех элементов массива
b = a * 2 => [2, 4, 6, 10, 14, 16, -20]
Умножение массива на массив с помощью выражений АЕ невозможно.
1.3 Теперь рассмотрим функции объекта Math с массивами
Допустим нам надо вычислить значения синуса. Конструкция Math.sin(a)
не сработает и вернет нам результат NaN
. Поэтому самое время добавить к нашим знаниям метод применения функции ко всем элементам массива. Метод объекта массива map
не вошел в АЕ, но зато вошел метод apply
объекта Function
. Итак применим функцию вычисления синуса к массиву:
b = Math.sin.apply([], a)
Конструкция выглядит немного странно, потому что формально мы применяем метод не к массиву, а к функции, и ей передаем массив в качестве аргумента. При этом наш массив это второй аргумент, первый аргумент указывает на прототип данных и нам не важен. Однако ж здесь нас ждет разочарование, результатом этой функции в АЕ будет значение только первого элемента. Пока я еще пытаюсь найти решение, однако же есть как минимум две очень полезные функции объекта Math
, которые работают таким способом, это Math.max
и Math.min
. Таким способом мы можем быстро найти максимальное или минимальное значение в массиве:
b = Math.max.apply([], a)
или (по идее правильнее)
b = Math.max.apply(Math, a) => 8
И тут давайте ввернем полезный метод slice
объекта Array
.
Он поможет нам отсечь часть массива, например:
b = a.slice(2,5) => [3, 5, 7, 8]
Второй аргумент опциональный, если его нет, берется все до конца
b = a.slice(3) => [5, 7, 8, -10]
А теперь применим все вместе и найдем в массиве минимальное значение между вторым и пятым элементом:
b = Math.min.apply([], a.slice(2, 5)) => 3
1.4 Теперь все функции и методы массивов
Наш исходный массив все тот же:
a = [1, 2, 3, 5, 7, 8, -10]
Количество элементов в массиве (длина массива)
a.length => 7
Преобразования массива в строку
a.toString() => "1, 2, 3, 5, 7, 8, -10"
a.toLocaleString()
Преобразование в строку исходного кода
a.toSource() => "[1, 2, 3, 5, 7, 8, -10]"
Объединение массивов/значений в массив последовательно
a.concat(32,53,75) => [1, 2, 3, 5, 7, 8, -10, 32, 53, 75]
a.concat([32,53,75]) => [1, 2, 3, 5, 7, 8, -10, [32, 53, 75]]
Переворот массива (обратная последовательность элементов)
a.reverse() => [-10, 8, 7, 5, 3, 2, 1]
Cлияние массива в строку с разделителем (символ разделителя указан в операнде)
a.join(";") => "1;2;3;5;7;8;-10"
Cортировка массива (по возрастанию)
a.sort() => [-10, 1, 2, 3, 5, 7, 8]
Аргументом функции sort может выступать другая функция, но в АЕ этот метод похоже не работает
Извлечение части массива
// по первому и последнему индексам элементов
a.slice(4) => [7, 8, -10]
a.slice(3, 5) => [5, 7]
// по индексу и количеству элементов
a.splice(2) => [3, 5, 7, 8, -10]
a.splice(2,4) => [3, 5, 7, 8]
В JS этот метод может так же удалять и вставлять значения в массив, но не поддерживается в АЕ
Все предыдущие методы работы с массивами возвращали измененные значения, следующие же методы изменяют сам массив, поэтому в примерах указываются два значения, первое - новое значение массива a
, второе - возвращаемое значение b
.
Отброс последнего элемента массива с укорочением его длины, возвращает выброшенное значение (последний элемент)
b = a.pop() => a = [1, 2, 3, 5, 7, 8] b = -10
Такая же операция но с нулевым элементом массива (сдвиг массива)
b = a.shift() => a = [2, 3, 5, 7, 8, -10] b = 1
Вставка значений
// в конец массива с увеличением его длины, возвращает новую длину массива
b = a.push(-9,-8,-7) => b = [1, 2, 3, 5, 7, 8, -10, -9, -8, -7] a = 10
b = a.push([-9,-8,-7]) => b = [1, 2, 3, 5, 7, 8, -10, [-9, -8, -7]] a = 8 вставленный элемент тоже массив
// в начало массива с увеличением его длины, возвращает новую длину массива
b = a.unshift(-2, -1, 0) => b = [-2, -1, 0, 1, 2, 3, 5, 7, 8, -10, -9, -8, -7] a = 10
b = a.unshift([-2, -1, 0]) => b = [[-2, -1, 0], 1, 2, 3, 5, 7, 8, -10, -9, -8, -7] a = 8 вставленный элемент тоже массив
2. Строки
Не будем рассматривать бестолковые методы html-форматирования, они нам вряд ли понадобятся. Вот их перечень на случай, если вы захотите оформить что-то в html: .anchor
.big
.blink
.bold
.fixed
.fontcolor
.fontsize
.italics
.link
.small
.strike
.sub
.sup
Создание строки s
s = "something" => "something"
s = String("something") => "something"
s = new String("something") => "something"
s = String(a) => "1, 2, 3, 5, 7, 8, -10"
Строки (объект String
) по сути тоже являются массивами, но все их элементы это символы. Поэтому некоторые методы строк очень схожи с методами массивов. Так же как и с массивами вы можете обращаться к символам внутри строки по индексу, нумерация так же начинается с нуля.
Для всех следующих примеров возьмем за основу строку:
str = "test this thing"
Строка является по сути символьным массивом:
str[6] => "h"
str.charAt(6) => "h"
Длина строки (количество символов)
str.length => 15
Индекс первого найденного включения строки (символа или символов) в строке
str.indexOf("i") => 7
str.indexOf("thing") => 10
str.indexOf("x") => -1
Индекс последнего найденного включения строки (символа или символов) в строке
str.lastIndexOf("i") => 12
str.lastIndexOf("thing") => 10
str.lastIndexOf("a") => -1
Извлечение строк
str.substr(m,[length]) // начиная с индекса по количеству символов
str.slice(a,b) // между указанными индексами
str.substring(m,[n]) // межу казанными индексами, n - опционально
str.split("s", [n]) // разбиение строки на массив строк, разделитель - символ s, n - лимит. Пример `str.split(" ", 3) => ["test", "this", "thing"]
str.charCodeAt() // код символа по индексу (позиции) в строке
Сложение строк
str + str2
str.concat(str2)
a = ["hello","there","!"]
a.join(" ") => "Hello there !"
Сравнение, поиск
str.localeCompare() // сравнение строк с кучей опций (см. документацию по Java)
str.match(regexp) // проверка строки на соответствие Regular Expression (см. документацию по Regular Expressions)
str.replace(regexp,str2) // замена подстроки по Regular Expression. Пример: `ss.replace(/thing/gi,"thing")` => "test this thing"
str.search("s" or regexp) // поиск внутри строки s или Regular Expression
Регистр
str.toLocaleLowerCase()
str.toLowerCase() // перевод строки в нижний регистр
str.toLocaleUpperCase()
str.toUpperCase() // перевод строки в верхний регистр
Конвертация
str.toString()
str.valueOf()
parseInt(string) // извлечение целого числа из строки
2.1 Дополнительно полезно:
instanceOf // тест на тип данных объекта. Пример: `a instanceOf Array = true`
eval(string) // вычисление арифметического выражения внутри строки
("00000000" + Number).substr(-n) // Добавить n нулей перед числом Number
function.length // количество аргументов функции
function.arguments() // аргументы функции
function.name() // имя функции
function.prototype.call() // вызов функции как метод (похоже на apply но к набору значений)
function.toString() // получение исходного кода функции (если функция объяdлена в коде)
str.toSource() // исходный код объявления строки
3. Примеры
Перевернуть порядок слов (разделитель - пробел)
s.split(' ').reverse().join(' ') => "thing this test"
Сумма элементов массива. Здесь массив записывается в виде строки суммы и затем вычислется с помощью инструкции eval
eval(valList.join('+'))
Минимальный элемент массива
b = Math.min.apply(Math, a)
Максимальный элемент массива
b = Math.max.apply(Math, a)