Избранное »

22.09.2014 – 07:27 | 2 комментария | 15 105 views

Здравствуйте все, кто работает в Индизайне!
Извещаем вас о том, что на youtube.com начал работу канал «InDesign Мастерская вёрстки». Там уже размещены более 60 видео с полным описанием как работать с программой DoTextOK. Другие интересные темы, касающиеся работы …

Читать полностью »
Работа в InDesign

Хитрости и секреты, приемы работы, уроки

Новая версия!

Особенности новой версии Индизайна

Плагины

Описание плагинов, информация о плагинах для работы с Adobe InDesign

Скрипты

Готовые к использованию скрипты для Adobe InDesign

Скриптинг

Описание языка, приёмов и методов программирования для Adobe InDesign

Home » Скриптинг

Свойство geometricBounds, единицы измерения

Добавлено на 25.04.2012 – 02:29One Comment | 1 551 views

Свойство geometricBounds является одним из самых употребительных при решении задач автоматизации верстки в Индизайне при программировании на языке JavaScript.  Оно определяет координаты объектов на полосах издания. Представляет собой массив, состоящий из 4-х элементов строкового или числового типа, который содержит координаты Х и Y верхнего левого и правого нижнего углов какого-либо объекта (см. рис.).

Например, координаты можно задать так:

with(myTextFrame){
geometricBounds = ["61p", "4p", "62p", "45p"];
}

или при создании нового объекта в в составе метода add()

var myTextFrame = textFrames.add({geometricBounds:["0pt", "0pt", "100pt", "100pt"]})

Здесь задание координат Y1, X1, Y2, X2 производится при помощи массива из четырех членов. В нашем случае это четыре строки, но чаще используются числа.

geometricBounds = [25, 40, 100.5, 80.25];

Заметьте, что первой координатой в паре X-Y является координата Y. Следует также помнить, что в качестве разделителя между целой и дробной частью в числовых единицах измерения используется точка, а не запятая. Начинающие разработчики часто набивают себе шишки на этом. Возможно также задание единиц измерения, где в качестве разделителя между целой и дробной частью стоит единица измерения, напр., 1p6 т.е. 1 пика + 6 пунктов.
Если при задании geometricBounds не указаны никакие единицы измерения, например:

geometricBounds = [0,0,72,72]

то при выполнении скрипта InDesign будет использовать те единицы измерения, которые сейчас установлены для документа.
В скриптах единицы измерения задаются в установках документа viewPreferences. Для этого используется следующий код:

myDoc = app.activedocument;
// задаем единицы измерения picas
with (myDoc.viewPreferences){
	horizontalMeasurementUnits = MeasurementUnits.picas;
	verticalMeasurementUnits = MeasurementUnits.picas;
}

Здесь horizontalMeasurementUnits — единицы измерения для горизонтальной шкалы, verticalMeasurementUnits — для вертикальной.
Если надо задать другие единицы измерения, то внутри конструкции with используйте строки:

horizontalMeasurementUnits = MeasurementUnits.points;
verticalMeasurementUnits = MeasurementUnits.points;
//или
horizontalMeasurementUnits = MeasurementUnits.inches;
verticalMeasurementUnits = MeasurementUnits.inches;
//или
horizontalMeasurementUnits = MeasurementUnits.inchesDecimal;
verticalMeasurementUnits = MeasurementUnits.inchesDecimal;
//или
horizontalMeasurementUnits = MeasurementUnits.millimeters;
verticalMeasurementUnits = MeasurementUnits.millimeters;
//или
horizontalMeasurementUnits = MeasurementUnits.centimeters;
verticalMeasurementUnits = MeasurementUnits.centimeters;
//или
horizontalMeasurementUnits = MeasurementUnits.ciceros;
verticalMeasurementUnits = MeasurementUnits.ciceros;

Если вы хотите использовать в скрипте единицы измерения, отличные от тех, которые в настоящий момент использует InDesign, то хорошим тоном считается по окончании работы скрипта вернуть всё на место, как было до запуска скрипта. Фирма Adobe Systems в составе демонстрационных скриптов приводит пример этого:

 //ResetMeasurementUnits.jsx
var myDocument = app.activeDocument;
with (myDocument.viewPreferences){
	// Сохраняем старые единицы измерения в переменных myOldXUnits, myOldYUnits
	var myOldXUnits = horizontalMeasurementUnits;
	var myOldYUnits = verticalMeasurementUnits;
	// Устанавливаем новые единицы измерения
	horizontalMeasurementUnits = MeasurementUnits.points;
	verticalMeasurementUnits = MeasurementUnits.points;
}
//----------------------------------------------------------
// Основной код скрипта
//----------------------------------------------------------
// Возвращаем Индизайну старые единицы измерения
with (myDocument.viewPreferences){
	try{
		horizontalMeasurementUnits = myOldXUnits;
		verticalMeasurementUnits = myOldYUnits;
	}
	catch(myError){
		alert("Could not reset custom measurement units.");
	}
}

Определять и задавать единицы измерения можно с использованием прототипов:

var myDocument = app.activeDocument;
myDocument.prototype.setUnitsTo = function(newUnits)
{
var arrUnits = (newUnits.length) ? newUnits : [newUnits,newUnits];
with(this.viewPreferences)
	{
	horizontalMeasurementUnits = arrUnits[0];
	verticalMeasurementUnits = arrUnits[1];
	}
}
Document.prototype.getUnits = function()
{
return([
	this.viewPreferences.horizontalMeasurementUnits,
	this.viewPreferences.verticalMeasurementUnits
	]);
}

В тексте программного модуля затем формируется массив из двух значений и устанавливаются новые единицы измерения

var units = this.activeDocument.getUnits();
app.activeDocument.setUnitsTo(MeasurementUnits.points);

В конце работы программы возвращаются первоначальные единицы измерения:

app.activeDocument.setUnitsTo(units);

 

О чем молчит Adobe

Если требуется рассчитать geоmetricBounds для текстового фрейма, у которого размер равен размеру страницы, то можно воспользоваться функцией, которую приводит фирма Adobe в своих примерах:

myDocument = app.activeDocument
with(myDocument.documentPreferences){
var myPageWidth = pageWidth;
var myPageHeight = pageHeight;
}
var myPage = app.activeWindow.activePage;
var myTextFrame = myPage.textFrames.add(
{
geometricBounds:[0, 0, myPageHeight, myPageWidth]
}
);

Конечно редко нужно создавать текстовый фрейм размером на всю страницу. Гораздо чаще требуется ограничить создаваемый фрейм полями страницы. Рассмотрим функцию myGetBounds() (демонстрационный пример Adobe), которая рассчитывает geometricBounds в этом случае.

var myDocument = app.activeDocument;
var myTextFrame = myPage.textFrames.add({geometricBounds:myGetBounds(myDocument, myPage), contents:TextFrameContents.placeholderText});
function (myDocument, myPage)
{
var myPageWidth = myDocument.documentPreferences.pageWidth;
var myPageHeight = myDocument.documentPreferences.pageHeight
if(myPage.side == PageSideOptions.leftHand){
var myX2 = myPage.marginPreferences.left;
var myX1 = myPage.marginPreferences.right;
}
else{
var myX1 = myPage.marginPreferences.left;
var myX2 = myPage.marginPreferences.right;
}
var myY1 = myPage.marginPreferences.top;
var myX2 = myPageWidth - myX2;
var myY2 = myPageHeight - myPage.marginPreferences.bottom;
return [myY1, myX1, myY2, myX2];
}

Как видите, для правильного расчета координат в скрипте используются свойства по определению положения страницы на развороте — правая или левая (.leftHand). Но тем не менее здесь скрыт подводный камень, о котором Adobe не сказала ни слова. Засада в том, что функция myGetBounds() правильно определяет массив координат geometricBounds только в том случае, если у каждой страницы своё начало координат и своя координатная система. Если же система координат общая для всего разворота, то рассчитанные координаты для правой страницы будут неверны, и создаваемый текстовый фрейм вместо правой страницы окажется на левой. Странно, что этот факт нигде не отражен в примерах скриптов фирмы Adobe.
Для того, чтобы эта функция всегда правильно работала, перед её вызовом надо установить отдельную координатную систему на каждую страницу разворота

myDocument.viewPreferences.rulerOrigin = RulerOrigin.pageOrigin;
var myTextFrame = myPage.textFrames.add({geometricBounds:myGetBounds(myDocument, myPage), contents:TextFrameContents.placeholderText});

Если вы намерены менять координатную систему, то по окончании работы скрипта будет благородно вернуть её назад:

var oldRuler = myDocument.viewPreferences.rulerOrigin;
myDocument.viewPreferences.rulerOrigin = RulerOrigin.PAGE_ORIGIN;
var myTextFrame = myPage.textFrames.add({geometricBounds:myGetBounds(myDocument, myPage), contents:TextFrameContents.placeholderText});
// выполняем скрипт
//...............
// Возвращаем первоначальную систему координат
myDocument.viewPreferences.rulerOrigin = oldRuler;

Вы уже заметили использование параметра RulerOrigin.PAGE_ORIGIN? Этим параметром произведена установка одного из типов координатной системы. В Индизайне их три: spread, page, spine. Соответственно в объектной модели (раздел Preference > viewPreferences) свойство ruleOrigin может принимать значения RulerOrigin.SPREAD_ORIGIN, RulerOrigin.PAGE_ORIGIN, RulerOrigin.SPINE_ORIGIN.

Второй вариант получения всегда правильных координат заключается в модификации функции myGetBounds(), где происходит разветвление расчета в зависимости от установленной в текущий момент системы координат:

function myGetBounds(myDocument, myPage){
var myPageWidth = myDocument.documentPreferences.pageWidth;
var myPageHeight = myDocument.documentPreferences.pageHeight;
myRuler = myDocument.viewPreferences.rulerOrigin;
if(myPage.side == PageSideOptions.leftHand){
var myX2 = myPage.marginPreferences.left;
var myX1 = myPage.marginPreferences.right;
}
else{
if(myRuler == RulerOrigin.pageOrigin || myRuler == RulerOrigin.spineOrigin)
{
var myX1 = myPage.marginPreferences.left;
var myX2 = myPage.marginPreferences.right;
}
else // система координат общая для разворота
{
var myX1 = myPageWidth + myPage.marginPreferences.left;
var myX2 = myPageWidth + myPage.marginPreferences.right;
}
}
var myY1 = myPage.marginPreferences.top;
var myX2 = myPageWidth - myX2;
var myY2 = myPageHeight - myPage.marginPreferences.bottom;
return [myY1, myX1, myY2, myX2];
}

В этом случае менять и возвращать первоначальную координатную систему не требуется. Теоретически этот способ более медленный, но вряд ли на практике вы это заметите.

One Comment »

  • eugenyus:

    С этим «pageOrigin» тоже нужно держать ухо востро. Простой пример: создаём документ с тремя страницами (смысл — нужен именно разворот), задаём линейке параметр «Ruler Per Page» и запускаем такой скрипт (рисует текстовый фрейм на правой странице разворота… в смысле, нам надо, чтоб нарисовал):

    var myDoc = app.activeDocument;
    var p = myDoc.pages;
    var pb = p[2].bounds;
    p[2].textFrames.add({geometricBounds:pb});

    А теперь зададим линейке параметр «Ruler Per Spread» и запустим тот же скрипт. У меня результат отличается. А у вас? )))

Оставить комментарий!

Вы должны быть в системе чтобы оставить комментарий.