[ предыдущая страница ] [ следующая страница ] [ содержание ]

6.3. Применение динамических текстовых полей

Динамические текстовые поля - самый распространенный способ вывода какой-либо информации для пользователя по ходу исполнения ролика. Вообще говоря, этот метод является чуть ли не единственным. Можно, конечно, выводить информацию в окно Output (Вывод) с помощью оператора trace (к этому мы еще вернемся в разделе 6.5) или с помощью оператора fscommand вызывать функции JavaScript, такие, как, например, alert().

Однако эти способы не очень удобны и надежны. Например, trace-сообщения иногда вообще не выводятся на экран (об этом мы еще поговорим в разделе, посвященном экспорту и публикации роликов), а запускать сложный механизм взаимодействия технологий Flash и JavaScript только ради вызова модального окна alert - все равно, что покупать сложный инженерный калькулятор для того, чтобы посчитать, сколько будет 28+34.

6.3.1. Динамический вывод текста

Если нужно по ходу ролика Flash вывести текстовую информацию для пользователя, используют, как правило, динамические текстовые поля. Напомним, что каждому такому полю ставится в соответствие переменная, имя которой определяется на вспомогательной панели Text Options (Параметры текста) в поле Variable (Переменная). Чтобы обновить содержимое динамического текстового поля, нужно просто присвоить этой переменной новое значение.

В качестве первого примера рассмотрим создание динамического поля, отображающего количество секунд, прошедших от начала воспроизведения ролика. Такое поле может, например, пригодиться в предварительном загрузчике.

Откройте новый ролик и создайте текстовое поле. Установите размер шрифта, равный 42, и выберите гарнитуру с кириллическими символами. С помощью панели Text Options (Параметры текста) сделайте это поле динамическим и назовите соответствующую ему переменную sec. Мышью увеличьте размер поля, чтобы наши надписи туда поместились. Откройте сценарий первого кадра и напишите в нем следующий код:

q = getTimer();
sec = "Прошло "+Math.floor(q/1000)+" секунд";

Здесь мы считываем количество прошедшего времени с помощью функции getTimer(), а затем делим его на 1000 (чтобы получить количество секунд) и округляем в меньшую сторону с помощью метода Math.floor(). Склеив это значение со словами "Прошло" и "секунд", присвоим получившуюся строку переменной sec. Теперь нужно добавить в шкалу времени обычный кадр, чтобы обеспечить цикличность исполнения кода первого кадра. Напомним, что если этого не сделать, то сценарий исполнится только один раз и, соответственно, в динамическом поле застынет надпись "Прошло 0 секунд".

Циклы внутри кадра

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

while (true) {
   q = getTimer();
   sec = "Прошло "+Math.floor(q/1000)+" секунд";
}

ведь в этом случае код тоже исполняется циклически?

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

Почему так происходит? Дело в том, что содержимое кадра не перерисовывается до тех пор, пока содержащийся в кадре сценарий не выполнен до конца. Соответственно, бесконечный цикл просто останавливает исполнение любого ролика. Именно поэтому программа периодически проверяет, сколько времени исполняется сценарий, и в случае подозрения на бесконечный цикл предлагает пользователю прервать его.

В прошлых версиях программа поступала еще "круче": любой цикл, содержащий более 200000 проходов, автоматически считался бесконечным, и исполнение сценария прерывалось без запроса к пользователю.

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

gotoAndPlay (1);

Корректировка грамматики

Просмотрим наш ролик. Все бы ничего, однако иногда возникают грамматические неточности (ну что за фраза "Прошло 21 секунд"?). Попробуем исправить это. Вначале вычислим значение целых секунд и присвоим его промежуточной переменной qq. Содержимое динамического поля sec будем складывать из переменной р (принимающей значение "Прошла" или "Прошло" в зависимости от значения переменной qq), самой переменной qq и переменной a (принимающей значение "секунд", "секунды" или "секунда"). Поскольку формы "Прошла" и "секунда" нужны в том случае, когда значение переменной qq заканчивается на 1 (кроме числа 11), можно проверить, чему равен остаток от деления qq на 10:

if ((qq%10==1)&&(qq!=11)) {
   р = "Прошла ";
   s = " секунда";
}
else {
   р = "Прошло ";
   s = " секунд";
}

Аналогичным образом можно добавить проверку на необходимость использования формы "секунды". Вот какой сценарий получится в результате:

q = getTimer();
qq = Math.floor(q/1000);
if ((qq%10==1)&&(qq!=11)) {
   p = "Прошла ";
   s = " секунда";
}
else if (((qq%10>=2)&&(qq%10<=4))&&((qq<10)||(qq>20))) {
   p = "Прошло ";
   s = " секунды";
}
else {
   p = "Прошло ";
   s = " секунд";
}
sec = p+qq+s;

Просмотрите ролик еще раз. Теперь все фразы построены грамматически правильно: "Прошла 31 секунда", "Прошло 32 секунды" и так далее. Правда, если пользователь дождется значения в 111 секунд, опять начнутся неправильности. Поскольку 111 не равно 11, при данном значении qq сценарий использует формы "Прошла " и " секунда". В качестве самостоятельного упражнения попробуйте исправить наш сценарий, обеспечив корректное построение фраз с числами 111-114, 211-214 и так далее.

Если писать сообщения на английском языке, то подобных проблем оказывается намного меньше. При создании русскоязычных сообщений иногда возникает желание махнуть рукой на разнообразие грамматических форм, уповая на то, что пользователь поймет наши проблемы. ("В конце концов, пишет же одна из русских версий Netscape в строке состояния надписи типа "Осталось 24 secов", а почему мне нельзя?" - говорил мне один знакомый.) Однако мы настоятельно рекомендуем не пренебрегать построением грамматических форм в подобных случаях. На пользователя (особенно неопытного) такие вещи производят отталкивающее впечатление.

6.3.2. Отображение свойств объектов

Рассмотрим другой простой пример - отслеживание координат мыши. Создайте новый ролик, а в нем мувик. В мувик поместите два динамических текстовых поля. Одно назовите xx, а другое - yy. Поместите в рабочую область экземпляр этого мувика. Откройте окно сценария объекта Object Actions (Действия объекта) (именно объекта, а не кадра!) и поместите туда такой код:

onClipEvent (mouseMove) {
   xx = _xmouse;
   yy = _ymouse;
}

Все! Теперь в наших динамических полях постоянно отображаются координаты указателя мыши. Правда, если внимательно присмотреться, можно заметить, что координаты (0,0) расположены не в левом верхнем углу ролика, а где-то посередине. Дело в том, что мы расположили код внутри мувика и координаты мыши отсчитываются относительно его центра. Если мы хотим выводить значения координат мыши для основного ролика, нужно изменить код так:

onClipEvent (mouseMove) {
   хх = _root._xmouse;
   yy = _root._ymouse;
}

В этом случае в динамические поля выводятся значения свойств _xmouse и _ymouse для объекта _root, то есть основного ролика.

6.3.3. Анимация вывода

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

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

on (release) {
   toprint = "Листь"+chr(255)+" в поле пожелтели,"+newline+"И кружатьс"+chr(255)+", и лет"+chr(255)+"т,"+newline+"Лишь в бору поникши ели"+newline+"Зелень мрачную хран"+chr(255)+"т.";
}

Особенности формирования строк

Пока что здесь все понятно - при просмотре ролика достаточно щелкнуть на кнопке, и в динамическом поле появится текст. Дадим небольшие пояснения по поводу того, как формируется строковое значение.

В некоторых версиях Flash в окне ввода сценария возникают некоторые проблемы с русской строчной буквой "я" (в кодировке Windows). Например, если попытаться присвоить переменной строковое значение "Листья в поле", программа Flash выведет сообщение об ошибке, так как интерпретатор ActionScript "споткнется" на букве "я", решив, что на этом месте произошел обрыв начатой строковой константы. Поэтому эту букву приходится вводить в виде кода - chr(255).

Далее, чтобы осуществить переход на новую строку, необходимо ввести соответствующий код. Разработчики ActionScript решили нам помочь и избавили от необходимости запоминать код перехода на новую строку. Они придумали функцию newline, которая всегда возвращает этот код.

Постепенное формирование надписи

Осуществим постепенное появление надписи. Ясно, что при нажатии на кнопку строка должна быть присвоена переменной toprint не вся целиком, а сначала одна буква, потом первые две и так далее. Поэтому присвоим приведенное выше строковое значение не сразу переменной toprint, а сначала вспомогательной переменной a. Это можно сделать уже в первом кадре ролика, только давайте сначала создадим специальный слой для сценариев и назовем его Actions.

Как выделить из строки ее часть? Для этого существует строковая функция substring, в которой нужно указать исходную строку, номер символа, с которого начинается фрагмент, и количество символов во фрагменте. Обратите внимание, что третий аргумент - количество символов, а не номер первого невыделенного символа, как в языке JavaScript или методе substring объекта String. Нумерация символов начинается с нуля.

Таким образом, если написать в сценарии кнопки

on (release) {
   toprint = substring(a,0,1);
}

то в динамическое поле будет выведен только первый символ строки. Очевидно, что если ввести вспомогательную переменную i, присвоив ей значение 1, а затем написать вместо предыдущего варианта

toprint = substring(a,0,i++);

то при каждом нажатии кнопки "Напечатать" в текстовое поле будет выведено на один символ больше.

Однако это не то, что нам нужно. Зациклить сценарий (чтобы при каждом шаге цикла печаталась следующая буква) мы тоже не можем - тогда кадр перерисуется только после завершения сценария, когда в переменной toprint уже содержится вся строка целиком.

Выход из положения следующий: основной текст сценария нужно разместить не в кнопке, а в основном ролике. А щелчок на кнопке должен просто запустить основной ролик с соответствующего кадра. Так и сделаем. В первом кадре остановим основной ролик и заодно присвоим переменной i начальное значение 1. Во втором кадре разместим уже знакомую нам строку

toprint = substring(a,0,i++);

а в третьем осуществим возвращение во второй кадр:

gotoAndPlay (2);

В кнопке просто поместим команду перехода на второй кадр. Кроме того, хорошо бы не заставлять компьютер совершать лишнюю работу по окончании вывода стихотворения. Это можно сделать, сравнив значение переменной i с длиной строки a:

if (i==length(a)) stop ();

Интересно, что программа допускает в данном случае и употребление метода length объекта String, то есть можно написать как length(a), так и a.length. Кстати, таким же образом можно применять к обычным строковым данным все методы объекта String, кроме concat, fromCharCode, slice и substr. Разумеется, в основном слое (в котором содержатся динамическое текстовое поле и кнопка) следует добавить обычный кадр во вторую (а "для красоты" можно и в третью) позицию.

Звуковое сопровождение

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

Щелкнув на кнопке Edit (Изменить) вкладки Sound (Звук), установим маркеры начала и конца звука так, чтобы отрезать возможные пустоты в начале и в конце (особенно это актуально для начала звука). Теперь при каждой прорисовке второго кадра (в котором печатается новая буква) раздается короткий звуковой сигнал. На всякий случай, к оператору остановки ролика по завершении печати текста можно добавить оператор выключения звука stopAllSounds.

Подбор временных характеристик

Просмотрите ролик. В принципе, мы добились, чего хотели: при нажатии на кнопку в динамическое поле постепенно, буква за буквой выводится текст сообщения, да еще и с "озвучкой". Но все это происходит слишком быстро - глаз не успевает следить, звуки, хотя и короткие, смешиваются друг с другом. Чтобы избежать этого, достаточно поставить в третьем кадре перед оператором gotoAndPlay небольшую задержку, которую можно осуществить с помощью функции getTimer():

t = getTimer();
while (getTimer()-t<200);

Здесь пустой цикл while задержит переход обратно во второй кадр как минимум на 200 миллисекунд, или 1/5 секунды. Можно поставить любой временной интервал по своему усмотрению.

Итак, посмотрим, что получилось. В первом кадре расположен такой сценарий:

a = "Листь"+chr(255)+" в поле пожелтели,"+newline+"И кружатьс"+chr(255)+", и лет"+chr(255)+"т,"+newline+"Лишь в бору поникши ели"+newline+"Зелень мрачную хран"+chr(255)+"т.";
i = 1;
stop ();

Во втором кадре расположен наш основной код:

toprint = substring(a,0,i++);
if (i==a.length) {
   stop ();
   stopAllSounds ();
}

И, наконец, сценарий третьего кадра:

t = getTimer();
while (getTimer()-t<200);
gotoAndPlay (2);

При этом в кнопке "Напечатать" расположено следующее:

on (release) {
gotoAndPlay (2);
}

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

6.3.4. Прокрутка текстовых полей

А мы перейдем к очередному примеру - осуществлению прокрутки ("скроллинга") текста в полях ввода. В многострочных полях ввода <TEXTAREA> в документах HTML прокрутка осуществляется автоматически. Что же касается полей ввода в программе Flash, то здесь - вынужден огорчить читателя - автоматическая прокрутка пока что не предусмотрена. Точнее говоря, при перемещении курсора по тексту он, в случае необходимости, прокручивается, но никакой полосы прокрутки при этом не появляется, и привычные методы прокрутки не проходят. Иногда может показаться, что в поле виден весь текст, хотя большая его часть скрыта и расположена снизу или сверху от видимой части текстового поля.

Общего рецепта управления прокруткой в полях ввода программы Flash не существует, однако в организации такого управления могут помочь такие свойства полей, как scroll и maxscroll. Значение свойства scroll всегда равно номеру самой верхней видимой строки поля. А значение maxscroll равно такому значению свойства scroll, при котором последняя строка текста видна в нижней части текстового поля. Значение свойства maxscroll изменить невозможно - оно зависит от количества введенных строк. А вот изменяя значение свойства scroll, можно программно прокручивать текст в поле ввода.

Кнопки прокрутки

Приведем простейший пример. Создайте текстовое поле ввода (его можно назвать input), а рядом разместите две кнопки, одну со стрелкой вверх, другую со стрелкой вниз. Лучше всего сделать сами кнопки невидимыми, а стрелки разместить в мувиках на тех же местах. Мувики можно назвать, например, u и d. В первый кадр можно поместить такой код:

if (input.scroll<2) u._visible = false;
else u._visible = true;
if (input.scroll==input.maxscroll) d._visible = flase;
else d._visible = true;

Это код прячет кнопки, если прокрутка в соответствующую сторону невозможна. Кнопке со стрелкой вверх можно назначить такой сценарий:

on (release) {
   input.scroll--;
}

а кнопке со стрелкой вниз - такой:

on (release) {
   input.scroll++;
}

В основном ролике при этом нужно не забыть сделать количество кадров большим чем 1. Если сейчас просмотреть ролик и попытаться ввести в поле какой-либо достаточно длинный текст, можно заметить, что ролик ведет себя довольно дружелюбно: при возможности прокрутки вниз или вверх появляются соответствующие стрелочки, а при нажатии на них мышью текст в поле привычно прокручивается.

Поскольку количество видимых строк в текстовом поле известно заранее, можно, используя это число и свойство maxscroll, установить между стрелками и движок, как в обычных окнах Windows. Его перемещение мышью также должно приводить к прокрутке текста. Однако для создания такого движка нужно познакомиться с тем, как организовать в ролике перетаскивание объектов мышью. Об этом мы поговорим в следующей главе. А пока что оставим проблему создания движка на полосе прокрутки в качестве отложенного упражнения - вернитесь к этой теме самостоятельно после изучения раздела 7.3.

[ предыдущая страница ] [ следующая страница ] [ содержание ]
Hosted by uCoz