May 25, 2017

Работа с массивами и строками в выражениях After Effects (статья в разработке)

* Эта статья находится в разработке, многое еще ищется и добавляется*

Это небольшой справочник, который я решила сделать для себя и всех, кто часто использует выражения при работе в Adobe After Effects. Поскольку выражения являются подмножеством JS, то многие возможности ускользают от пользователей After Effects, мало знакомых с программированием. Я решила пройтись по JS и протестировать совместимые функции и методы. Надеюсь этот справочник поможет вам успешнее использовать выражения в вашей работе и применять больше генеративных возможностей. Этот справочник будет уточняться и расширяться. Все, что здесь написано, проверено для версии CC 2014.



Массивы

Массив (объект Array) это объект, в котором сохранено некоторое количество других объектов, где каждому из них сопоставлен последовательный номер (индекс элемента). Элементы называются объектами, т.к. не имеют четкого типа. Вы можете смешивать в массиве значения разных типов (например и числовые и текстовые). Но за этим кроются некоторые подводные камни. Для простоты будем пока рассматривать одномерный массив вида: [1, 2, 3, 5, 7, "eight", -10]
Операции с массивам перебором элементов в цикле это громоздко и медленно, давайте посмотрим, какие возможности нам предоставляет Java Script. Начнем с базовых арифметических операций. Для этого нам надо избавиться от текстового значения в примере выше, иначе мы получим сообщение об ошибке, т.к аримфетические операции не могут применяться к текстовым значениям. Для следующих примеров возьмем за исходный массив:
a = [1, 2, 3, 5, 7, 8, -10]
Я наверное опущу такие простые операции, как извлечение элемента массива вида b = a[3], когда в результате переменной b мы присваиваем значение третьего элемента. Не забывайте, что нумерация элементов массива начинается с нуля.



Сложение и вычитание массивов

b = a + 1
В данной операции правый операнд рассматривается как массив из одного элемента, то есть выглядит как a + [1], таким образом единица добавится к нулевому элементу массива а, получаем:
[1, 2, 3, 5, 7, 8, -10] => [2, 2, 3, 5, 7, 8, -10]
Отсюда легко догадаться каков будет результат следующей операции:
b = a + [1, 1, 1]
К первым трем элемента будет добавлено по единице:
[1, 2, 3, 5, 7, 8, -10] => [2, 3, 4, 5, 7, 8, -10]

Умножение и деление

b = a * 2
Здесь все работает немного по-другому, и операция умножения или деления выполняется для всех элементов массива. Результат:
[1, 2, 3, 5, 7, 8, -10] => [2, 4, 6, 10, 14, 16, -20]
Умножение массива на массив невозможно.


Теперь рассмотрим функции объекта 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:
[1, 2, 3, 5, 7, 8, -10] => 8

И тут давайте ввернем полезный метод slice объекта Array. Он поможет нам отсечь часть массива, например:
b = a.slice(2,5)
вернет нам массив, который будет копией элементов со 2 по 5 массива a:
[1, 2, 3, 5, 7, 8, -10] => [3, 5, 7, 8]
Или вот так (второй аргумент опциональный, если его нет, берется все до конца)
b = a.slice(3)
вернет нам все, начиная с третьего элемента:
[1, 2, 3, 5, 7, 8, -10] => [5, 7, 8, -10]
А теперь применим все вместе и найдем в массиве минимальное значение между вторым и пятым элементом:
b = Math.min.apply([], a.slice(2, 5))
получим значение 3
[1, 2, 3, 5, 7, 8, -10] => 3

Теперь все функции и методы массивов по порядку

Количество элементов в массиве (длина массива)
b = a.length => 7
Преобразования массива в строку
a.toString() => "1, 2, 3, 5, 7, 8, -10"
a.toLocaleString()
Преобразование в строку исходного кода
a.toSource() => "[1, 2, 3, 5, 7, 8, -10]"
Объединение массивов/значений в массив последовательно
b = a.concat(32,53,75) => [1, 2, 3, 5, 7, 8, -10, 32, 53, 75]
b = a.concat([32,53,75]) => [1, 2, 3, 5, 7, 8, -10, [32, 53, 75]]
Переворот массива (обратная последовательность элементов)
b = a.reverse() => [-10, 8, 7, 5, 3, 2, 1]
Cлияние массива в строку с разделителем (символ разделителя указан в операнде)
b = a.join(";") => "1;2;3;5;7;8;-10"
Cортировка массива (по возрастанию)
b = a.sort() => [-10, 1, 2, 3, 5, 7, 8]
Аргументом функции sort может выступать другая функция, но в АЕ этот метод похоже не работает

Извлечение части массива (по первому и последнему индексам элементов)
b = a.slice(4) => [7, 8, -10]
b = a.slice(3, 5) => [5, 7] 
Извлечение части массива (по индексу и количеству элементов)
b = a.splice(2) => [3, 5, 7, 8, -10]
b = a.splice(2,4) => [3, 5, 7, 8]
В JS этот метод может так же удалять и вставлять значения в массив, но не поддерживается в АЕ 

Все предыдущие методы работы с массивами возвращали измененные значения, следующие же методы изменяют сам массив, поэтому в примерах указываются два значения, первое - новое значение массива a, второе - возвращаемое знавчение b.

Отброс последнего элемента массива с укорочением его длины, возвращает выброшенное значение (последний элемент)
b = a.pop() => [1, 2, 3, 5, 7, 8] -10
Такая же операция но с нулевым элементом массива (сдвиг массива)
b = a.shift() => [2, 3, 5, 7, 8, -10] 1
Вставка значений в конец массива с увеличением его длины, возвращает новую длину массива
b = a.push(-9,-8,-7) => [1, 2, 3, 5, 7, 8, -10, -9, -8, -7]  10
b = a.push([-9,-8,-7]) => [1, 2, 3, 5, 7, 8, -10, [-9, -8, -7]]  8
Вставка значений в начало массива с увеличением его длины, возвращает новую длину массива
b = a.unshift(-2, -1, 0) => [-2, -1, 0, 1, 2, 3, 5, 7, 8, -10, -9, -8, -7]  10
b = a.unshift([-2, -1, 0]) => [[-2, -1, 0], 1, 2, 3, 5, 7, 8, -10, -9, -8, -7]  8

Строки

Не будем расматривать бестолковые методы 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" 
s = str[2] => "s"
s = ss.charAt(2) => "s"
Длина строки (количество символов)
b = str.length => 15
Индекс первого найденного включения строки (символа или символов) в строке
b = str.indexOf("i") => 7
b = str.indexOf("thing") => 10
b = str.indexOf("x") => -1
Индекс последнего найденного включения строки (символа или символов) в строке
string.lastIndexOf("i") => 12
string.lastIndexOf("thing") => 10
string.lastIndexOf("a") => -1 

string.charCodeAt() - код символа по индексу
ss + "" = ss.concat("") - идентично, сложение строк
string.localeCompare() - сравнение строк с кучей опций (см документацию по яве)
string.match(regexp) - проверка строки на соответствие Regular Expression
string.replace(regexp,"") - замена подстроки по Regular Expression. Пример:
 ss.replace(/thing/gi,"shit") => "test this shit"
string.search("s" or regexp) - поиск внутри строки s или Regular Expression
string.slice(a,b) - извлечение строки между указанными индексами
string.split("s", [n]) - разбиение строки на массив строк, разделитель - символ s, n - лимит
b = ss.split(" ", 3) => ["test","this","thing"]
string.substr(m,[length]) - извлечение строки с индекса по количеству символов
string.substring(m,[n]) - извлечение строки межу казанными индексами
string.toLocaleLowerCase() str.toLowerCase() - перевод строки в нижний регистр
string.toLocaleUpperCase() str.toUpperCase() - перевод строки в верхний регистр
string.toSource() - исходный код объявления строки
string.toString()
string.valueOf()

Дополнительно полезно:

instanceOf - установление типа объекта. Пример: a instanceOf Array = true
eval(string) - вычисление арифметического выражения внутри строки
parseInt(string) - извлечение целого числа из строки
("00000000" + Number).substr(-n) Добавить n нулей перед числом Number

= еще будет =

операции с массивами строк
многомерные массивы

function.length - количество аргументов функции
function.arguments() - аргументы функции
function.name() - имя функции
function.prototype.call() - вызов функции как метод (похоже на apply но к набору значений)
function.toString() - получение исходного кода функции (если функция объялена в коде)


Примеры

Перевернуть порядок слов (разделитель - пробел)
s.split(' ').reverse().join(' ')  => "thing this test"
Сумма элементов массива. Здесь массив записывается в виде строки суммы и затем вычислется с помощью инструкции eval
eval(valList.join('+')) 
Минимальный элемент массива
b = Math.min.apply(Math, a) 
Максимальный элемент массива
b = Math.max.apply(Math, a) 

1 comment:

  1. King casino bonus codes 2021 : Play in this one!
    The Jackpot King vua nhà cái Casino bonus codes will appear on this page カジノ シークレット as shown in the top left corner of the page, and you dafabet can use this code to claim your bonus.

    ReplyDelete