Создание календаря автоматически, используя скрипт.
Создание графического календаря вручную, нелегкая задача. Именно поэтому лучше найти способ автоматизировать процесс. В этом уроке будет показано, как в Фотошопе сгенерировать календарь на весь год, используя JavaScript. Если вы знаете программировании – это замечательно, но если нет — не волнуйтесь, описание довольно прозрачное (единственно, очень внимательно записывайте команды, в некоторых местах регистр также имеет значение):
Предварительный просмотр:
Список свойств и методов, поддерживаемых Фотошопом CS4, с примерами,
можно скачать здесь – это даст общее представление относительно
того, как выглядят и за что отвечают команды используемые в скрипте.
Если у вас предыдущая версия фотошопа, то необходимые документы вы
можете найти тут (при желании, после прочтения темы, это
руководство может помочь решить свои задумки по автоматизации).
Шаг 2
Давайте приступим. Главная идея
состоит в том, чтобы создать текстовые слои на каждый месяц, содержащие
даты. Поэтому главным образом мы будем работать вокруг генерации текста.
Запустите ExtendScript Toolkit
(идет в комплекте с Фш) и создайте новый файл JavaScript. Он
будет содержать все команды, которые мы собираемся задать для Фотошопа.
Если вы не хотите использовать ExtendScript
Toolkit, то можете работать в любом текстовом редакторе.
Шаг 3
Сначала мы определяем переменные значения, которые будут использованы при создании документа и систему
цветов календаря. Я задал размеры 1280 на 800рх, при разрешении в
72 pixels/inch, с именем “PhotoshopScriptCalendar”
и выбрал 2010-й как год календаря, который мы создаем:
Рассмотрим цвета, которые мы задали и к чему они будут впоследствии применены. “NormalColor” — для названий месяцев,
будних чисел и дней. Цвет столбика воскресных дней будет зависеть от
строчки “highlightColor“, а “backColor” — это соответственно фоновый
цвет календаря:
документа
width = 1280;
height = 800;
resolution = 72;
docName
= “PhotoshopScriptCalendar”;
year = 2010;//Cистема цветов
normalColor
= new SolidColor();
normalColor.rgb.hexValue = “FFFFFF”;
highlightColor
= new SolidColor();
highlightColor.rgb.hexValue = “A4B1D1”;
backColor
= new SolidColor();
backColor.rgb.hexValue = “1B4392”;
Шаг 4
Поскольку мы главным образом
собираемся работать с текстом, то следует определить для него некоторые
переменные, которые мы собираемся неоднократно использовать в заголовках
месяцев (название месяцев и дней можно писать кириллицей):
Чтобы
получить цвет колонки с воскресеньем отличным от остальных дней, нам
нужно сделать его отдельным текстовым слоем. Поэтому мы зададим в коде
два заголовка: “monthHeader” – от
понедельника до субботы (пробелы будут учитываться как расстояние), и “sundayHeader” – воскресение. Каждая из
этих двух переменных заканчивается двумя “\r“.Они поддерживают перенос текста на новую строку,
как нажатие на клавишу ENTER. Затем определим переменную сдвига
первого числа года на нужный день – “firstIdent“.
Так как первое января было в пятницу, то мы должны учесть предыдущие
ячейки дней и сделать необходимое число пробелов, которое будет зависеть
от используемого шрифта и его размера, что проверяется опытным путем
нескольких проб. Наконец, запишите все названия месяцев в порядке их
следования:
переменных для текстовых слоев
monthHeader = “Пн Вт
Ср Чт Пт Сб\r\r”;
sundayHeader
= “Вс\r\r”;
firstIndent = ” “;months = new Array(“Январь”, “Февраль”, “Март”, “Апрель”,
“Май”, “Июнь”, “Июль”, “Август”, “Сентябрь”, “Октябрь”, “Ноябрь”,
“Декабрь”);
Шаг 5
Теперь, когда у нас есть все
необходимые объекты, мы можем начать создавать .psd документ:
Как
вы видите, код довольно понятен и удобочитаемый. Здесь задана команда
создания нового документа с посыланием на значения ширины, высоты,
разрешения и названия, которые были внесены ранее в 3-м шаге (посылание в
скобках), также указывается цветовое пространство. По умолчанию все
новые документы создаются в цветовом пространстве RGB, поэтому
можно было опустить этот параметр, но если вы хотите изначально создать
другое пространство, например CMYK, то так и записываете в
отведенном месте “NewDocumentMode. CMYK“.
То же и с другими цветовыми моделями, просто записываете их название
после точки: LAB, GRAYSCALE, BITMAP и т.д.
Далее мы
записывает команду выделения всего документа (думаю понятно, что этой
команде соответствует строка “doc.selection.selectAll()“),
команду заливки и снятия выделения:
нового документа
doc = app.documents.add(width, height, resolution,
docName,
NewDocumentMode.RGB);
doc.selection.selectAll();
doc.selection.fill(backColor);
doc.selection.deselect();
Шаг 6
Затем мы прописываем добавление
начального фона из стороннего изображения. Градиентный фон, что виден на
окончательном результате, по сути является отдельным изображением. Для
этого мы собираемся использовать функцию “openDialog
()” – она запускает диалоговое окно File
> Open, что позволит выбрать изображение с жесткого
диска:
Ниже прописываем следующую строчку. Мы
собираемся использовать только первое выделенное изображение (вы ведь
знаете, что в фотошопе можно разом открыть несколько пикчей — а в данном
случае нужно всего одно, но ведь можно случайно выбрать и два), поэтому
для множества “file” вписываем 0.
Но также мы должны поставить проверку на то, было ли вообще выбрано
какое-либо изображение “if“:
Затем
изображение загружается и его окно становится активным, что мы
прописываем “app.activeDocument“:
Изменяем
размеры изображения к нашим параметрам. Снова прописываем выделение
всего документа, потом копируем выделенную область и закрываем документ
сохранения изменений (полагаю, что смысл прописанных внутри операций
виден и понятен фотошоперам невооруженным глазом — ведь что такое “selectAll“, “fill” и прочие названия знакомо всем):
Наконец,
запишем команду вставки (ясно, что после закрытия, активным
автоматически становится предыдущий документ), что приведет к помещению
скопированного изображения на слой выше фонового. Заодно зададим слою
название, например “BackgroundImage“.
Заметьте,
что если при выборе изображения нажать Cancel, то все действия
этого шага, после первой строчки, не выполняются (потому что мы
прописали команды только при варианте наличия выбора изображения,
помните “if“. Тобишь, если не
нужна заморочка со вставкой картинки, ведь ее можно и потом добавить, то
можно вообще не делать этот шаг):
фонового изображения
file = app.openDialog();if(file[0]){
app.load(file[0]);
backFile
= app.activeDocument;
backFile.resizeImage(width, height);
backFile.selection.selectAll();
backFile.selection.copy();
backFile.close(SaveOptions.DONOTSAVECHANGES);
doc.paste();
doc.layers[0].name
= “Фоновое изображение”;
}
Шаг 7
Хорошо, приступим к
самой генерации календаря (пишем на строчку ниже). Данный этап может
показаться немного сложным, но мы будем продвигаться вперед шаг за
шагом, и, надеюсь он немного прояснится.
Необходимо сделать набор
действий, участвующих в создании каждого месяца (основу повторения
действий). Используем петлю назначения “for“,
в которой переменная “curr”
используется, чтобы обозначить текущий месяц, с которым мы работаем.
Начальное значение для “curr”
устанавливаем на 0, а конечное на 12 – это значит, что
набор написанных позже действий будет прокручиваться 12 раз, в
количестве месяцев года. Это-то нам и нужно (тем, кто хоть краем мозга
знакомился с программирование, логика построения строчки должна быть
понятной):
Сначала мы должны определить две
переменные, которые собираемся использовать, чтобы расположить наши
месяцы на холсте в виде сетки. Ими будут X и Y –
координаты осей горизонтали и вертикали. При данных размерах холста
разумно разместить на один ряд 4 месяца, таким образом для параметра
смещения X, отвечающего за горизонталь, мы собираемся
использовать операцию “%“. В
результате деления переменной “curr”
на 4, получаем три ряда. Для оси Y мы используем функцию javascript
– “Math.floor ()” (тут я не
совсем въехал в смысл описания, но цифра та же)
Гораздо
удобнее, если создаваемые текстовые слои, для всех месяцев, будут
находится в отдельных одноименных папках. Посему запишем создание
таковых папок, имена которые будут получать по очереди из уже готового
списка, что мы определили ранее:
curr<12; curr++){x = curr % 4;
y= Math.floor(curr / 4);
group
= doc.layerSets.add();
group.name = months[curr];
}
Шаг 8
Далее мы создаем новый текстовый
слой внутри группы и определяем его имя соответствующее названию группы
текущего месяца:
Теперь
мы должны установить текстовые атрибуты, такие как цвет, размер шрифта и
выключку. Мы установим тип ввода нашего текста “PARAGRAPHTEXT” (способ с ограничивающей рамкой) и
зададим ему определенные размеры. Атрибут для “contents” в переменной “monthName”
обозначает фактический текст, что будет виден в слое – нам же нужно
название определенного месяца, поэтому мы поставим и ставим “months[curr]” (напомню любителям, что в
программировании часто идут ссылки на определенные, ранее прописанные
строки, с их свойствами и значениями… короче атрибутами, чтобы ими
воспользоваться. Это как в математике, когда определенный повторяющийся
участок формулы мы приравниваем к иксу и далее, для упрощения писанины,
используем уже Икс, зная при этом истинное его значение. Так вот,
атрибуты для months мы прописали в
начале кода, а заданная переменная curr, с каждым витком подставит
следующее значение от months):
Также
давайте развернем текст на 90° против часовой стрелки и
разместим в определенном месте на слое (здесь мы собираемся использовать
наши переменные смещений “x” и “y“):
Имейте
в виду, что расположение сделано относительно верхнего левого угла, но
так как мы произвели вращение на 90° против часовой стрелки – это
теперь стало нижним левым углом. Если вы задали для своего документа
иные размеры, чем в уроке, то вам придется соответственно изменить
константы, которые я использовал у себя:
curr<12; curr++){x = curr % 4;
y= Math.floor(curr / 4);
group
= doc.layerSets.add();
group.name = months[curr];
monthName =
group.artLayers.add();
monthName.kind = LayerKind.TEXT;
monthName.name
= months[curr];
monthName.textItem.color = normalColor;
monthName.textItem.size
= 27;
monthName.textItem.kind = TextType.PARAGRAPHTEXT;
monthName.textItem.justification
= Justification.RIGHT;
monthName.textItem.height = 35;
monthName.textItem.width
= 145;
monthName.textItem.contents = months[curr];
monthName.rotate(-90);
monthName.textItem.position
= new Array(55 + 300 * x, (202 + (210 * y)));
}
Шаг 9
На этом этапе мы собираемся сделать
текстовый слой, который впоследствии будет содержать все даты текущего
месяца, кроме воскресений. Сейчас мы сделаем так, чтобы слой был
добавлен в ранее созданную группу, а также определим имя слою, выключку,
цвет шрифта, размер и позицию расположения. Содержание слоя мы добавим
чуть позже и когда мы дойдем до того пункта я объясню почему:
Та
же самая процедура и для воскресной колонки, только цвет другой — “highlightColor“:
= group.artLayers.add();
days.kind = LayerKind.TEXT;
days.name =
“Days”;
days.textItem.Justification = Justification.CENTER;
days.textItem.color
= normalColor;
days.textItem.size = 19;
days.textItem.position =
new Array(85 + (300 * x), 70 + (210 * y));sundays =
group.artLayers.add()
sundays.kind = LayerKind.TEXT;
sundays.name =
“Sundays”;
sundays.textItem.Justification = Justification.CENTER;
sundays.textItem.color
= highlightColor;
sundays.textItem.size = 19;
sundays.textItem.position
= new Array(280 + (300 * x), 70 + (210 * y));
}
Шаг 10
Теперь мы должны создать две
переменные, которые будут вмещать генерируемый текст: переменная “text” будет содержать будние дни, “textSun” — даты воскресенья. Начинаем с
добавления заголовков столбиков и отступа первого числа на нужный день
недели для первого месяца. Создание новой даты делается через функцию javascript
“Date()” — функции года нашего
календаря с месяцами и получения их позиции по неделях (я так понял
берет данные из “даты и времени” на компьютере). Помните, нумерация
всегда начинается от 0, так например, если первым в столбике
месяца будет понедельник, то “n” =
0, если это будет вторник, то “n”
будет 1 и так далее. Тогда мы должны добавить заявку, которую мы
определили вначале к переменной “text“,
столько раз, сколько необходимо. Например, если первой в месяце будет
среда, то мы добавим заявку два раза:
= monthHeader;
textSun = sundayHeader;startDate = new
Date(year, curr, 1);
n = startDate.getDay();
for(i=0;
i<n-1; i++)
text += firstIndent;
}
Шаг 11
Настало время для генерации всех
чисел месяца. Для этого мы должны знать, сколько дней в каждом
конкретном месяце, и нам нужны числа в формате “leading zeros” —
таким образом мы должны вернутся и определить две вспомогательных
функции: “daysInMonth” и “makeDay“. Вернитесь к началу кода и
добавьте эти функции.
Функция “daysInMonth”
— возвращает нужное количество дней для данного месяца, который мы
делаем (определяет их для каждого месяца согласно данным календаря на
компьютере).
Функция “makeDay”
— возвращает данное ей число в определенном формате (добавляет нули к
числам меньшим 10 — в коде это видно из условия, что если d
меньше 10, то перед ним нужно добавить цифру 0) и задает
расстояние между цифрами чисел дней (в пробелах между кавычками строчки
return d + ” “ — его следуем
задавать с учетом пробелов между названиями дней недели).
Так,
например, если мы вызовем функцию “daysInMonth”
со значением для year = 2010
(год мы указали в параметрах документа) и month = 0 (что будет означать
Январь), то мы получим 31 сгенерированный день в заданном месяце.
Если мы вызовем функцию “makeDay“,
например, с d = 3, то это возвратит нам текст “03” (добавит
ноль впереди), но если d = 13, то число “13” таким и
останется:
вспомогательных функций
function daysInMonth(month, year){
return
32 – new Date(month, year, 32).getDate();
}function
makeDay(d){
if(d < 10)
d = “0” + d;
return d + ”
“;
}
Спуститесь назад, книзу кода. Мы начнем со значения “d = 1“, оно будет увеличиваться, пока не достигнет
числа количества дней в месяце. Если “i” равняется шести — это означает, что настало воскресенье, таким образом
мы должны добавить дату к воскресному слою. Не забудьте записать “\r“, для сноса последующего текста на
новую строчку. Иначе в эту же строчку будут добавляться следующие будние
числа.
Теперь мы добавляем новую строчку, только если текущий
день суббота (i=5). В конце мы должны увеличить обе “i” и “d“. При значении “i“, когда оно достигает “7“, если последним
днем было добавлено воскресенье, оно должно вернутся к первому столбику,
а значит мы должны указать это, прировняв его к “0” (в этом
блоке я мог что-то и неправильно перевести):
Теперь
у нас есть все даты в наших текстовых переменных и мы можем добавить их
к нашим слоям. Причина задержки этого шага заключается в том, что
поочередное добавление дат к слою занимает время работы Фотошопа,
поэтому лучше добавить все сразу, вместо того, чтобы добавлять каждый
день отдельно:
= 1;
while(d <= daysInMonth(curr, year)){
if(i == 6)
textSun
+= makeDay(d) + “\r”;
else{
text += makeDay(d);
if(i == 5)
text
+= “\r”;
}
i++;
d++;
if(i == 7)
i = 0;
}days.textItem.contents
= text;
sundays.textItem.contents = textSun;
}
Шаг 12
Итак, код генерации всех чисел есяца готов, а сейчас мы пропишем добавление слоя с годом и создания
небольшой линии в основании документа. Для слоя с годом — процедура та
же, что мы использовали прежде: создание слоя, переименование, указание
размета с цветом и местоположения на холсте:
Для
линии у основания код немного иной. Сначала мы должны определить
область с координатами X и Y для всех четырех углов, затем
сделать выделение этой области, а потом залить ее и снять выделение:
Создание текстового слоя с годом
yearLayer = doc.artLayers.add();
yearLayer.kind
= LayerKind.TEXT;
yearLayer.name = year;
yearLayer.textItem.contents
= year;
yearLayer.textItem.size = 72;
yearLayer.textItem.color =
highlightColor;
yearLayer.textItem.position = new Array(1050, 730);//Создание
нижней линии
line = doc.artLayers.add();
line.name = “Line”;
region
= Array(Array(80, 729), Array(1000, 729), Array(1000, 730), Array(80,
730));
doc.selection.select(region);
doc.selection.fill(normalColor)
doc.selection.deselect();
Шаг 13
Код скрипта готов! Единственная вещь, которую осталось сделать, так это воспользоваться им. Если вы
пользовались программой ExtendScript Toolkit, то из выпадающего меню выберите Adobe Photoshop, если при этом фотошоп не запущен,
кликните на изображение маленькой цепи, а затем на кнопку запуска. Если Вы использовали любого рода текстовый редактор, вам остается сохранить
файл с расширением “.js” или “.jsx“, а потом запустить его в фотошопе через меню: File > Scripts > Browse… и выбрать этот сохраненный файл:
уменьшите максимальное значение для [curr] с 12 на 1 (чтобы не все
месяцы прокручивало, а только один), а уже после того, как достигнете
желаемого, вернете назад.
Автор: Alexandru Pitea
Перевел: Manoylov AC
Скачать скрипт на Рабочий стол: script23_calendar
Мой фотошоп CS4 (русский) обрабатывает этот скрипт, только нет ни в одном месяце дней и весь текст выводит в маленьком изображении, грубо говоря 5 на 5 пикселей. Подскажите, пожалуйста как исправить.
“Для оси Y мы используем функцию javascript
– “Math.floor ()” (тут я не
совсем въехал в смысл описания, но цифра та же)”
функция Math.floor () – округление с недостатком, к нижнему целому числу. т.е. если у нас число 4.99, то получим 4.0
Гораздо проще генерить сетку календаря в Кореле! Тем более, что она получается в вектором формате, а не растровом.
Да, англоязычная. Мой комп не тянет к сожалению 4 и 5 версии 🙁
У меня не вышло… стоит Photoshop CS 2, скачала эту программку для скрипта, только когда в начале сделала Run кода, то сразу выкинуло ошибку
normalColor = new SolidColor (); на этот код. и пишет ошибку : SolidColor does not have a constructor
undefined is not an object. и в программе не получается выбрать изображение, может в CS2 это не предусмотрено?
Урок очень нужный( а то недавно писала календарь от руки, замучалась ..)))
Я пользовался скриптом на CS4 и CS5 поэтому про CS2 сказать нечего не могу. Вы пользуетесь англоязычной версией фотошопа? Так как данный скрипт будет работать корректно только на англоязычной.