Работа со статичным текстом. Объект TextSnapshot

До Flash MX 2004 ActionScript не предоставлял никаких средств, позволяющих взаимодействовать с текстом в статичных полях. И это было вполне объяснимо. По определению, статичный текст неможет быть создан или изменен и процессе проигрывания фильма. Иначе между ним и динамическим текстом не было бы никаких различий. Полностью же отказаться от статичного текста в пользу динамического нельзя, так как поля типа Static обладают рядом полезнейших особенностей. Так, они используют символьный текст, который выглядит значительно лучше системного,— и это не приводит к значительному росту размера swf-файла. В случае статичного текста можно применить форматную выключку (проще говоря, выравнивание по обоим краям), которая оптимальна в случае больших текстовых фрагментов. В статичном тексте можно произвольным образом менять среднее расстояние между символами, растягивая или сжимая его. Поля типа Static предоставляют возможность создания вертикального текста. В общем, статичный текст может быть отформатирован куда лучше, чем текст типа Dynamic или Input. Поэтому, если текстовый фрагмент известен на этапе создания фильма и в дальнейшем его менять не придется, его стоит поместить именно и статичное текстовое поле.

Итак, операции программного задания или изменения статичного текста бессмысленны по определению.


Но вот некоторые операции типа READ ONLY как весьма востребованы практикой, так и не противоречат основным концепциям статичного текста. Особенно важны следующие:

• Если статичные текстовые поля в вашем фильме содержат большой объем текстовой информации, то стоит создать инструмент поиска вроде панели «Поиск на странице» Internet Explorer.

Для этого необходимо иметь возможность считывать содержимое текстовых полей в строку, а также выделять нужный фрагмент текста.

• Для реализации ряда текстовых эффектов бывает необходимо знать, к какому символу принадлежит точка с некоторыми координатами.

Необходимость решения описанных задач заставляла в предыдущих версиях Flash отказываться от использования статичного текста в пользу динамического. А это приводило к снижению качества форматирования, увеличению размера swf-файла. Поэтому во Flash MX 2004 разработчики ввели возможность осуществления основных операций типа READ ONLY со статичным текстом. Ее носителем являются объекты класса TextSnapshot.

Создание объектов класса TextSnapshot
TextSnapshot — это совершенно обычный класс. Поэтому его объекты могут быть созданы при помощи оператора new и конструктора.


В качестве параметра конструктор класса принимает ссылку на клип, с расположенным на временной диаграмме которого статичным текстом необходимо взаимодействовать. Например:

// Объект st_text будет связан со статичным текстом клипа clip
var st_text:TextSnapshot=new TextSnapshot(clip);

Приведенный способ создания объектов класса TextSnapshot является недокументированным. Официально желанные объекты создаются совсем по-другому. Для этого служит специальный метод getTextSnapshot() класса MovieClip. Он применяется по отношению к клипу, вложенный в который статичный текст должен быть обработан. Возвращает метод getTextSnapshot() объект класса TextSnapshot, связанный с соответствующим клипом. Пример:

var st_text:TextSnapshot = clip.getTextSnapshot();
trace(st_text); // Выводит: [object Object]
trace(st_text.__proto__ == TextSnapshot .prototype); // Выводит: true
// (созданный объект действительно принадлежит классу TextSnapshot)

Описанные способы создания объектов класса TextSnapshot абсолютно идентичны. Наверное, у вас возник вопрос о том, зачем тогда понадобилось вводить в ActionScript метод getTextSnapshot()(если он не дает никаких преимуществ по сравнению с конструктором класса.


Вероятно, этим самым разработчики из Macromedia хотели подчеркнуть тесную связь объекта TextSnapshot и клипа, частью которого является статичный текст. Реальной же функциональной необходимости в существовании метода getTextSnapshot() не имеется.

Ввиду их аналогичности вы можете использовать тот способ создания объектов класса TextSnapshot, который вам больше нравится. В рамках этой книги мы будем, дабы не вступать в противоречия с официальной документацией, применять метод getTextSnapshot(). В объекте класса TextSnapshot фиксируется статичный текст, который отображался в клипе в момент создания объекта. Если же клип переходит ни новый кадр или часть статичных полей удаляется (эту операцию можно провести, создав на соответствующих глубинах новые объекты), то автоматического обновления содержимого объекта TextSnapshot не происходит. Это означает, что он перестанет корректно описывать отображаемый статичный текст. Поэтому для каждого кадра или набора статичных полей необходимо создавать индивидуальный объект TextSnapshot.

Объект TextSnapshot взаимодействует только с непосредственно принадлежащими клипу статичными полями. Текст, относящийся к вложенным в клип клипам или кнопкам, им не учитывается.

Считывание текста статичных полей
Все статичные поля, расположенные на текущем кадре данного клипа, воспринимаются классом TextSnapshot как единое целое. Это означает, что нельзя определить, какой фрагмент текста принадлежит одному полю, а какой — другому. Весь статичный текст на кадре будет считан при создании объекта TextSnapshot в одну строку, причем никаких разделителей между подстроками, соответствующими разным полям, не будет. Прочитать данную строку или ее фрагмент можно, используя метод getText(). Его синтаксис:

t_sn_obj.getText(begin, end, line_endings),
где:

• t_sn_obj — объект класса TextSnapshot, адресуемый которым статичный текст должен быть прочитан;

• begin — индекс символа, начиная с которого должна быть считана подстрока из строки, хранящей объединенный текст всех статичных полей кадра. Отсчет символов ведется с 0;

• end — индекс символа, следующего за последним символом подлежащей выделению подстроки. Чтобы считать весь статичный текст кадра, параметру begin нужно присвоить значение 0, а параметру end – t_sn_obj.getCount() (метод getCount() служит для определения количества знаков в статичном тексте). Параметр end не может быть равным или меньшим параметра begin: при этом ему автоматически будет присвоено значение bcgin+1;

• line_endings — необязательная булева величина, определяющая, будут ли подстроки, соответствующие различным текстовым полям, разделяться при помощи символа переноса строки. Использовать данный параметр нужно осторожно, так как введение в возвращаемую методом getText() строку новых символов делает ее неприемлемой для определения параметров другими методами класса TextSnapshot. По умолчанию параметр line_endings равняется false: текст различных статичных полей никак не разделяется.
Пример использования метода getText():

// Создайте на главной временной диаграмме три статичных поля, занеся в них
// цифры 1, 2, 3
var st_text:TextSnapshot = _root.getTextSnapshot();
trace(st_text.getText(0,3)); // Выводит: 123

Порядок, в котором текст статичных полей конкатенируется в строку, зависит от занимаемых ими глубин. Чем меньше виртуальный слой, на котором располагается поле, тем ближе к началу используемой классом TextSnapshot строки будет находиться его текст. Чтобы в этом убедиться, распределите статичные поля по нескольким слоям, а затем проверьте, текст какого из них начинает возвращаемую методом getText() строку.

Некоторые приложения от Macromedia (например, Flash Paper — но не Flash MX2004) дают возможность присваивать статичным текстовым полям порядковые номера для ТАВ-обхода. Если для статичных полей данного клипа такая иерархия была создана, то конкатенация их содержимого в одну строку будет осуществлена исходя из нее.

В строку, описывающую статичный текст кадра, не включаются символы переноса строк. Никак в ней не отображаются и особенности форматирования текста: переносы, отступы. Кстати, в статичных текстовых полях нельзя использовать символы табуляции, поэтому в возвращенной методом getText() строке их быть не может.

Чтобы метод getText() мог выполнить возложенные на него функции, поля должны быть невыделяемыми и у них должна быть неактивной настройка Use Device Fonts.

Вместе с методом getText() зачастую используется метод getCount(). Данный метод возвращает количество символов в расположенном на кадре клипа статичном тексте. По своим особенностям он аналогичен свойству length класса String.

Поиск строки в статичном тексте
Основная задача, для решения которой используется класс TextSnapshot, связана с реализацией инструмента поиска в статичных текстовых полях. Конечно, справиться с этой задачей можно, анализируя возвращенную методом getText() строку при помощи метода indexOf() класса String.

Но можно поступить и проще, обратившись к специальному методу findText() класса TextSnapshot.

Его синтаксис:

t_sn_obj.findText(begin, text_to_find, caseSens),
где:

• t_sn_obj — объект класса TextSnapshot, связанный со статичными текстовыми полями, в которых должен быть осуществлен поиск;

• begin — индекс символа, с которого должен быть начат поиск в строке, хранящей текст статичных полей;

• text_to_find — строка, найти позицию которой необходимо;

• caseSens — булева величина, определяющая, будет ли при поиске учитываться регистр символов (true) или же нет (false).

Метод findText() возвращает индекс символа, начиная с которого искомая подстрока впервые встречается. Если в статичном тексте, начиная с позиции begin, подстрока ни разу не попадается, возвращается -1. Например:

// Создайте статичное поле и наберите в нем "Привет, друзья!"
var st_text:TextSnapshot = _root.getTextSnapshot();
var index:Number=st_text.findText(0,"друзья", false);
trace(index); // Выболит: 8
trace(st_text.getText(index,index+6)); // Выводит: друзья

Более реалистичный пример использования метода findText() мы рассмотрим в следующем подразделе, когда изучим инструменты, позволяющие выделять статичный текст.

Программное выделение статичного текста
При необходимости нужный фрагмент статичного текста можно выделить, используя метод setSelected() класса TextSnapshot. Однако выделение это будет особое, не похожее на выделение, с которым мы сталкиваемся в случае динамических полей и полей ввода. Можно отметить следующие его особенности:

• Программное выделение фрагмента статичного текста совершенно не привязано к фокусу. Оно может существовать, если в фокусе находится другой объект и даже если в это же время выделен участок текста в динамическом поле или поле ввода. Не исчезает такое выделение даже при щелчке левой кнопки мыши или нажатии клавиши клавиатуры.

• Программное выделение не сочетается с обычным. Поэтому его можно создать лишь в случае статичных полей с отключенной настройкой Selectable.

• По умолчанию цвет программного выделения не черный, а желтый. Его наведение не
сопровождается изменением цвета текста.

• Высота программного выделения варьируется в зависимости от собственной высоты символов. Высота же полосы обычного выделения одинакова и равна полной высоте строки.

• Программное выделение может быть наведено на разрозненные фрагменты статичного текста. Обычное же выделение может существовать только в виде целостного блока.
Проанализировав приведенные факты, можно сделать вывод о том, что программное выделение фрагментов статичного текста реально выделением не является. Скорее, это просто закрашивание заднего фона символов. Отсюда и все его особенности.

Основным инструментом при работе с программным выделением статичного тек-j ста является метод setSelected(). Он позволяет выделять нужные фрагменты текста, а затем снимать с них выделение. Его синтаксис:

t_sn_obj.setSelected(begin, end, select),
где:

• t_sn_obj — объект класса TextSnapshot, соответствующий статичному тексту, фрагмент которого должен быть выделен;

• begin — индекс символа, с которого должно начаться выделение. Допустимое для него значение лежите пределах от 0 до t_sn_obj.getCount() — 1. Если передать begin отрицательное число, оно будет заменено на 0. Если же данному параметру передано слишком большое значение, используется величина t_sn_obj.getCount() — 1;

• end — индекс символа, лежащего за последним символом подлежащей выделению подстроки.

Допустимые для него значения принадлежат интервалу от begin+1 до t_sn_obj.getCount(). Если end передано значение, меньшее begin+1, оно автоматически заменяется на begin+1. Если end не определен, по умолчанию используется значение t_sn_obj.getCount();

• select — булева величина, определяющая, выделение создается (true) или удаляется (false).

Так как программное выделение статического текста не зависит от расположения фокуса, единственный способ его удалить — использовать метод setSelected().

Суть работы метода setSelected() сводится к закрашиванию заднего фона каждого символа в пределах ограничивающей его рамки. Так как эта операция проводится индивидуально для каждого символа, повторно применив метод setSelected(), выделенными можно сделать разрозненные участки статичного текста. Добиться такого же эффекта в случае обычного выделения невозможно.

Цвет выделения, создаваемого методом setSelected(), по умолчанию желтый. Это не всегда приемлемо. Например, желтым может быть сам текст, а так как при программном выделении статичного текста смена цвета шрифта не происходит, он попросту сольется с фоном. Чтобы этого не произошло, цвет выделения нужно сменить. Для этого служит метод setSelectColor(rgb), где rgb — шестнадцатеричная формула необходимого оттенка. У ранних версий Flash Player 7 имеется довольно своеобразная особенность поведения метода set-
Selected(). Выделение визуализируется лишь в том случае, если на той же временной диаграмме имеется выделяемое статичное текстовое поле. Иначе оно создается (в этом можно убедиться при помощи метода getSelectedText()), но не отображается. Очевидно, что описанная особенность является банальной недоделкой (проще говоря, «багом»), и она, скорее всего, будет исправлена одним из ближайших обновлений плейера. Однако ее стоит учитывать, так как у пользователя может быть установлена именно ранняя подверсия Flash Player 7.

Приведем небольшой пример:

// Создайте клип clip со статичным полем. В результате работы следующего
// кода первый и последний символы его текста скажутся выделенными красной
// заливкой.
var st_text: TextSnapshot = clip.getTextSnapshot();
st_text.setSelectColor(0x3В0000);
st_text.setSelected(0, 1, true);
st_text.setSelected(st_text.getCount()-1, st_text.qetCount(), true);

Какой фрагмент статичного текста является выделенным, можно определить при помощи метода getSelectedText(). Данный метод возвращает строку, содержащую его. Если выделено несколько разрозненных фрагментов, они по порядку конкатенируются в одну строку. Если статичный текст, с которым связан данный объект класса TextSnapshot, не имеет выделенных символов, возвращается пустая строка.

У метода getSelectedText() имеется один необязательный параметр. Это булева величина, определяющая, будут ли разделены символом \n участки возвращаемой им строки, относящиеся к различным текстовым полям. По умолчанию данный параметр равен false: разделители в строку не встраиваются.

Метод getSelectedText() регистрирует лишь выделение, созданное методом setSelected(). Обычное выделение статичного текста им не обнаруживается.

Метод getSelectedText() может быть полезен, например, если выделенный фрагмент статичного текста должен быть скопирован в буфер по нажатии + или при активизации специальной пользовательской команды контекстного меню.

Иногда бывает нужно знать, имеется ли выделение в конкретном тексте. Решить эту задачу позволяет метод getSelected(begin, end), где begin —индекс символа, начинающего подстроку, наличие в которой выделения интересует, end — индекс символа, перед которым данная подстрока заканчивается. Если выделение на данном участке статичного текста имеется, getSelected() возвращает true. В противном случае результатом будет false. Чтобы проверить, имеется ли выделение в статичном тексте кадра в принципе, параметру begin необходимо передать 0, а end — величину, возвращенную методом getCount().

Наиболее важная задача, для решения которой может быть использована возможность программного выделения статичного текста, связана с созданием инструмента поискав полях типа Static.

Важность этой задачи обусловлена тем, что стандартный инструмент поиска на странице браузера не применим к Flash-сайтам. Заменять же статичные поля динамическими можно далеко не всегда.

Следующий код реализует простейший инструмент поиска в статичном тексте:

/* Создайте статичное поле, содержащее относительно большой текстовый фрагмент. Убедитесь, что оно является невыделяемым. Выше его создайте поле ввода и назовите его search_string. В него будет вводиться искомая строка. Далее создайте кнопку и назовите ее but. Она будет запускать поиск. Затем создайте еще одну кнопку с названием clear. Она будет уничтожать выделение.

*/
var st_text:TextSnapshot = _root.getTextSnapshot();
st_text.setSelectColor(0xFF0000);
but.onPress = function():Void {
// Если в статичном тексте имеется выделение, удаляем его
if (st_text.getSelected(0, st_text.getCount())) {
st_text.setSelected(0, st_text.getCount(), false);
}
// Переменная n будет хранить номер символа, на котором закончился
// прошлый этап поиска
var n:Number = 0;
// Проверяем на наличие строки весь текст
while (n // Производим поиск, начиная с символа, на котором завершился
// прошлый его этап
n = st_text.findText(n, search_string.text, false);
// Если строка на промежутке от символа с индексом n и до
// конца текста не встречается, обрываем работу кода
if (n == -1) {
return;
// Если строка была найдена, выделяем ее и переопределяем n
} else {
st_text.setSelected(n, n+search_string.text.length, true);
n += search_string.text.length;
}
}
};
// Код, удаляющий выделение
clear.onPress = function():Void {
if (st_text.getSelected(0, st_text.getCount())) {
st_text.setSelected(0, st_text.getCount() , false);
}
};

Определение ближайшего к точке символа статичного текста
В случае статичного текста можно чрезвычайно просто определить, какому символу принадлежит данная точка (или какой символ является к ней ближайшим). Для этого предназначен метод hitTestTextNearPos() класса TextSnapshot. Его синтаксис:

hitTestTextNearPos(x, у, maxDistance),
где:

• х и у — координаты точки, ближайший к которой символ нас интересует. Должны быть заданы в системе координат того клипа, которому принадлежит соответствующий статичный текст;

• maxDistance – максимальное расстояние, которое может разделять символ и точку, чтобы метод hitTestTextNearPos() посчитал их достаточно близкими для возврата конкретного результата. По умолчанию данный параметр равен 0. Это означает, что точка считается близкой к символу лишь в том случае, если она лежит в пределах ограничивающей его рамки.

Метод hitTestTextNearPos() проверяет, какой символ статичного текста расположен к точке ближе всего. Если расстояние до этого символа не превышает заданного лимита, возвращается его индекс в соответствующей статичному тексту строке, хранимой объектами класса TextSnapshot. Если клип не содержит статичных полей или расстояние до ближайшего символа больше maxDistance, возвращается —1.

Метод hitTestTextNearPos() можно использовать для реализации разного рода эффектов. Тем более, что определить, к какому символу принадлежит точка, в случае динамических полей можно лишь приблизительно. Типичнейшей же задачей, решить которую позволяет рассматриваемый метод, является реализация возможности выделения фрагмента статичного текста при помощи курсора мыши. Например:

// Создайте статичное поле с относительно объемным фрагментом текста
var st_text:TextSnapshot = this.getTextSnapshot();
var index:Number = -1;
// При нажатии левой кнопки мыши удаляем старое выделение и фиксируем,
// по какому символу произошел щелчок
this.onMouseDown = function():Void {
st_text.setSelected(0, st_text.getCount(), false);
index = st_text.hitTestTextNearPos(_xmouse, _ymouse);
};
// При движении указателя мыши проверяем, нужно ли рисовать выделение
// (об этом говорит значение переменной index). Если да, то создаем его от
// символа, нал которым произошло опускание левой клавиши мыши, до символа,
// над которым указатель располагается в данный момент.
this.onMouseMove = function():Void {
if (index!= -1) {
st_text.setSelected(0, st_text.getCount(), false);
var index_2:Number = st_text.hitTestTextNearPos(_xmouse, _ymouse.1000);
if (index_2>index) {
st_text.setSelected(index, index_2, true);
} else {
st_text.setSelected(index_2, index, true);
}
}
};
// Фиксируем, что правая кнопка мыша была отпущена
this.onMouseUp = function():Void {
index = -1;
};

В результате использования приведенного кода вы сможете выделять статичный тексте отключенной настройкой Selectable точно так же, как если бы он был выделяемым. Однако при этом сохранится возможность использования класса TextSnapshot, которая отсутствует у выделяемых полей.

Также при этом вы будете способны произвольно задавать цвет выделения, сможете ввести дополнительные возможности, такие как, например, одновременное выделение разрозненных текстовых фрагментов при нажатии клавиши . Полностью же полноценным программное выделение статичного текста можно сделать благодаря наличию во Flash MX 2004 возможности взаимодействия средствами ActionScript с буфером обмена.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела Action Script на эту тему:
Автоматическое удаление пробелов. Свойство condenseWhite
Встраивание в фильм целого шрифта
Динамическая замена выделенного текста. Метод replaceSel()
Динамическое задание выделения. Метод setSelection()
Задание и извлечение текста поля

Вернуться в раздел: Action Script / 13. Работа с текстом