Работа с клипами
Продолжаем изучение языка ActionScript. Поговорим о клипах (в смысле, экземплярах образцов-клипов) и выясним, какие инструменты для работы с ними предоставляет ActionScript. А таких инструментов немало…
Все находящиеся на рабочем листе клипы, для которых было задано имя, равно как и сам фильм, представляют собой экземпляры объекта MovieClip. Их создает сам Flash; нам же остается только использовать их свойства и методы.
Все клипы имеют тип данных "клип". Оператор typeof при передаче ему в качестве параметра клипа вернет строку "movieclip".
Доступ к нужному клипу
Прежде чем приступить к изучению объекта movieClip, нам следует выяснить, как же получить доступ к его экземплярам, т. е. клипам и самому фильму.
В начале этой главы говорилось, что обращение к экземпляру объекта осуществляется по его имени. Имя клипа задается с помощью панели Properties, а именно, поля ввода, расположенного в ее левом верхнем углу.
Задав имя клипа, мы можем получить к нему доступ из сценария. Так, если на рабочем листе присутствует клип саг, то для остановки вложенной в него анимации мы можем создать во внешней анимации такой сценарий, привязав его, скажем, к кнопке:
car.stop();
Здесь мы указываем имя соответствующего экземпляра объекта movieClip и, через точку, — метод stop, останавливающий воспроизведение анимации.
Если же мы хотим остановить вложенную анимацию клипа car из самого этого клипа, то нам нужно слегка изменить написанный нами сценарий:
this.stop();
и поместить его в этот клип. Модификатор this указывает на текущий экземпляр объекта, т. е. на клип car.
Мы можем вообще опустить модификатор this и записать наш сценарий коротко:
stop();
Но так делать не рекомендуется.
Если же нам нужно остановить воспроизведение вложенной анимации клипа wheel, являющегося составной частью клипа car, нам следует написать такой сценарий:
car.wheel.stop();
Здесь мы написали последовательно имена клипов car и wheel, разделив их точкой. Фактически мы осуществили доступ к внутреннему объекту.
Подведем итог. Чтобы получить доступ к методу или свойству какого-либо клипа, нужно перечислить имена всех клипов, в которые он вложен, через точку (создав таким образом путь), а уже потом указать нужный метод или свойство. Причем имена клипов указываются в порядке увеличения уровня вложенности в текущий клип (тот, который содержит сценарий). Если же нужно получить доступ к методу или свойству текущего клипа (к которому привязан данных сценарий), достаточно указать только этот метод или свойство.
Если нам нужно обратиться к методу или свойству анимации основного фильма из вложенного в нее клипа, мы воспользуемся модификатором _root. Так, мы можем поместить в клип wheel сценарий
_root.stop();
который остановит воспроизведение внешней анимации.
Чтобы получить доступ к внешнему объекту из внутреннего, используется модификатор _parent. Так, сценарий, помещенный в клип wheel:
_parent.stop();
остановит воспроизведение анимации клипа саг, в который вложен клип wheel.
А теперь необходимо заметить следующее. Пути доступа к клипам могут быть записаны двумя различными способами. И при написании сценариев мы уже использовали оба этих способа.
Во-первых, доступ к клипу можно получить по его абсолютному пути. Абсолютный путь всегда записывается, начиная от внешней анимации, для доступа к которой используется модификатор _root. Вот пример абсолютного пути (выделен полужирным шрифтом):
_root.car.wheel.gotoAndPiay(1);
Этот сценарий будет работать в любом вложенном клипе и в самой внешней анимации, поскольку путь доступа к нужному клипу всегда один и тот же.
Абсолютный путь очень хорош в тех случаях, когда мы хотим обратиться из одного вложенного клипа к другому, находящемуся очень "далеко" от первого. В такой ситуации применение абсолютного пути позволит сделать выражение более компактным.
Во-вторых, мы можем задать относительный путь. Относительный путь записывается относительно текущего клипа, в котором находится сценарий. Так, если нам нужно запустить воспроизведение анимации клипа car из сценария, находящегося в клипе wheel, мы напишем такой сценарий (относительный путь выделен полужирным шрифтом):
_parent.gotoAndPiay(1);
Относительные пути применяются, если нужно обратиться к другому клипу, находящемуся не очень "далеко". В противном случае он может стать очень длинным.
Для примера напишем два выражения с разными видами путей и сравним их:
_parent.gotoAndPiay(1);
_root.car.gotoAndPiay (1);
Очевидно, что выражение, использующее относительный путь, компактнее того, которое использует абсолютный. А вот еще два разных выражения, находящихся в клипе wheel и останавливающих внешнюю анимацию:
_parent._parent.stop();
_root.stop();
Видно, что второе выражение, использующее абсолютный путь, компактнее. Пути доступа к клипам могут быть весьма длинными, например:
_root.car.engine.electricPart.ignitor.spark();
Чтобы сократить их, можно использовать уже знакомое нам выражение с ключевым словом with:
with (_root.car.engine.electricPart) {
headlightLeft.on();
headlightRight.on();
ignitor.spark();
}
Для вставки в код сценария путей доступа к клипам панель Actions предоставляет специальные средства, а именно, кнопку, расположенную над областью редактирования кода:
При нажатии этой кнопки на экране появится диалоговое окно Insert Target Path (рис. 19.1).
Большую часть этого окна занимает иерархический список клипов, вложенных в основной фильм. (Сам основной фильм там также присутствует.) Переключатели Absolute и Relative, расположенные под списком, позволяют выбрать способ записи пути, соответствующий их названиям. А в поле ввода, расположенном над списком, мы можем ввести путь доступа к клипу вручную. И, разумеется, после задания нужного пути следует нажать кнопку ОК.
Управление воспроизведением анимации
Обычно каждый клип начинает воспроизводиться сразу же после загрузки и воспроизводится до последнего кадра его анимации. Однако, используя сценарии, мы можем управлять этими процессами, в частности, останавливать и запускать воспроизведение, а также воспроизводить фильм, начиная с заданного кадра.
Мы уже знакомы с методом stop объекта movieClip — он останавливает воспроизведение клипа. А чтобы запустить воспроизведение клипа с того места, где он был остановлен, нужно воспользоваться методом play:
car.play();
Для осуществления перехода на какой-либо кадр клипа служат методы gotoAndPlay и gotoAndstop. Первый выполняет переход на заданный кадр и начинает воспроизведение клипа с него. Второй же метод выполняет переход на заданный кадр, но воспроизведение не инициирует. В качестве единственного параметра оба этих метода принимают номер или имя кадра; причем если значение этого параметра имеет числовой тип, то оно трактуется как номер кадра, если строковый — то как его имя. Пример с использованием числового параметра:
car.gotoAndPlay(10);
Для управления текущим клипом можно пользоваться также действиями gotoAndPlay и gotoAndstop объекта movieClip.
Формат записи их вызова таков:
gotoAndPiay|gotoAndStop([<Имя сцены>,]<Номер или имя кадра>);
Здесь второй параметр задает, опять же, номер или имя кадра, на который будет выполнен переход. Первый же, необязательный, параметр задает имя сцены, содержащей этот кадр; если же параметр пропущен, то выполняется переход на кадр текущей сцены. Например:
gotoAndPiay(10);
gotoAndStop("Эпизод 1", х + 1);
Осталось упомянуть еще о двух методах объекта movieClip. Метод prevFrame перемещает бегунок на предыдущий кадр клипа, а метод next Frame — на следующий. Ни один из этих методов не принимает параметров.
Методы prevFrame и next Frame можно использовать, например, для создания средствами Flash презентации или слайд-шоу. Делается это так. Все изображения (слайды), которые должны войти в презентацию, помещают в отдельных кадрах фильма. К первому кадру фильма привязывается сценарий, содержащий одно-единственное выражение — stop (), которое остановит фильм на первом же кадре. После этого остается создать кнопки и привязать к ним сценарии, содержащие выражения this.prevFrame () и this.nextFrame (), которые будут выполнять переход соответственно на предыдущий и последующий кадр фильма, — и простейшее слайд-шоу готово!
Обработка событий, возникающих в клипах
Обработчики событий клипов имеют такой формат:
onClipEvent(<Событие>) {
<Тело обработчика>
}
Собственно, нам он уже знаком из главы 18. Вот пример такого обработчика:
onClipEvent(mouseDown) {
this.stop();
}
Этот обработчик выполняется в ответ на щелчок мышью на клипе и останавливает воспроизведение вложенной в него анимации. Его код должен быть привязан к самому клипу.
Внимание!
При написании обработчиков событий клипов крайне желательно использование модификатора this, возвращающего ссылку на текущий клип.
Можно создать обработчик, выполняющийся в ответ сразу на несколько событий, перечислив их имена через запятую. Вот так:
onClipEvent(mouseDown, mouseMove) {
stop();
}
Этот обработчик выполнится либо после щелчка мышью на клипе (событие mouseDown), либо после перемещения над клипом курсора мыши (событие mouseMove).
Теперь самое время выяснить, какие события поддерживаются объектом movieClip. Некоторые из них приведены в табл. 19.10; полный же список событий можно найти в интерактивной справке Flash.
Событие enter Frame возникает при воспроизведении очередного кадра анимации клипа. Это значит, что обработчик данного события будет выполняться постоянно с частотой, равной частоте кадров фильма, до тех пор, пока фильм не закончится. Это можно использовать для выполнения различных задач, например, для отслеживания курсора мыши.
События load и unload можно использовать для запуска или останова воспроизведения других клипов. Например, при загрузке какого-либо клипа воспроизведение другого клипа может приостанавливаться, а после выгрузки — продолжаться. Также можно написать сценарий, загружающий после выгрузки одного клипа другой и запускающий его на воспроизведение.
События mouseDown и mouseUp можно, по идее, использовать для создания на рабочем листе подобия кнопок. Но для таких целей лучше использовать полноценные кнопки Flash, создание которых было описано в главе 18.
Интересная особенность клипов Flash состоит в том, что они могут обрабатывать события кнопки. Для этого достаточно привязать к клипу "кнопочный" обработчик события, код которого показан ниже:
on (press) {
stop();
}
И клип будет вести себя как кнопка.
Полный список событий, поддерживаемых кнопками Flash, будет приведен далее в этой главе.
Управление клипами
А теперь рассмотрим средства, предоставляемые Flash для управления клипами, находящимися на рабочем листе.
Создание новых клипов
Flash предоставляет возможность создавать экземпляры-клипы на основе имеющихся в библиотеке образцов, дублировать уже созданные на рабочем листе клипы и даже создавать абсолютно новые клипы, не основанные на имеющихся в библиотеке образцах. Давайте выясним, как все это реализовано.
Дублирование существующего клипа
Проще всего, конечно, создать новый клип, продублировав уже имеющийся на рабочем листе, вместе с его графикой, анимацией и сценариями. Для этого используется действие duplicateMovieClip. Формат его вызова таков:
duplicateMovieClip(<Дублируемый клип>, "<Имя создаваемого клипа>", <Порядок перекрытия нового клипа>);
С первым параметром передается путь исходного клипа, который нужно продублировать. Со вторым параметром передается имя вновь создаваемого клипа; оно должно иметь строковый тип и быть уникальным. Последний, третий, параметр определяет порядок перекрытия нового клипа; он должен иметь числовой тип.
Однако при создании нового клипа способом дублирования нужно учесть четыре момента. Во-первых, содержимое переменных, объявленных в сценариях дублируемого клипа, а также его свойств не копируется в новый клип. Во-вторых, если дублируемый клип содержит анимацию, то в новом клипе она в любом случае начнет воспроизводиться с самого начала. В-третьих, созданный таким образом клип вкладывается в тот клип, в котором находится продублированный клип. В четвертых, созданные с помощью действия duplicateMovieClip клипы в порядке перекрытия всегда находятся "выше" созданных вручную.
Приведем пример сценария, использующего действие duplicateMovieClip и находящегося в клипе car:
duplicateMovieClip(wheel2, "wheels", 3);
(Мы только что приделали к нашему автомобилю пятое, запасное, колесо!)
Вместо действия duplicateMovieClip можно использовать одноименный метод объекта MovieClip. Вот формат его вызова:
<Дублируемый клип>.duplicateMovieClip ("<Имя создаваемого клипа>", <Порядок перекрытия нового клипа>);
Создание нового клипа на основе образца.
Сценарные образцы
Чтобы создать совершенно новый клип, основанный на библиотечном образце-клипе, используется метод attachMovie объекта movieClip. Формат его вызова следующий:
<Клип>.attachMovie("<Имя сценарного образца>",
"<Имя создаваемого клипа>", <Порядок перекрытия нового клипа>);
Метод attachMovie вызывается для клипа, в который должен быть вложен вновь создаваемый клип. Второй и третий параметры нам уже знакомы, так что не будем останавливаться на них. А вот о первом параметре нужно поговорить подробнее.
Дело в том, что для успешного использования в методе attachMovie образец-клип нужно превратить в так называемый сценарный — доступный для вызова из сценария. Сейчас мы выясним, как это делается.
Первым делом нужно вывести на экран панель Library. Далее найдем в списке этой панели нужный образец и выберем в контекстном или дополнительном меню пункт Linkage, после чего на экране появится давно знакомое нам диалоговое окно Linkage Properties (см. рис. 8.21).
Чтобы превратить образец в сценарный, нужно включить флажок Export for ActionScript и ввести идентификатор создаваемого образца в поле ввода Identifier. Все почти так же, как и в случае разделяемых образцов.
Далее нам нужно решить, куда будут помещены массивы данных этого сценарного образца. По умолчанию все они помещаются в первый кадр фильма и, соответственно, загружаются перед тем, как фильм начнет воспроизводиться. Если таких образцов слишком много или если они очень велики, пауза перед выводом первого кадра фильма может затянуться. Но мы можем заставить Flash поместить массив данных образца в тот кадр фильма, в котором они впервые встречаются. Для этого достаточно отключить флажок Export in first frame.
Однако здесь нас подстерегает другой сюрприз. Если мы не использовали где-либо в фильме сценарный образец, то Flash не поместит его в результирующий файл Shockwave/Flash, справедливо полагая, что он здесь лишний. Что мы там написали в сценариях, его (Flash) не касается. Так вот, для того чтобы Flash все же сохранил сценарный образец в готовом фильме, нам придется все-таки поместить его экземпляр на рабочий лист, задав для него либо очень маленькие размеры, либо максимальную прозрачность.
Вот, собственно, и все. Осталось нажать кнопку ОК окна Linkage Properties. И можно использовать готовый сценарный образец.
Приведенный ниже сценарий добавит в наш автомобиль лишнюю фару, создав ее на основе сценарного образца headlight:
_root.car.attachMovie("headlight", "headlight3", 0);
Создание "пустого" клипа
Flash также позволяет поместить на рабочий лист "пустой" клип. Это выполняется с помощью метода createEmptyMovieClip объекта movieClip. Формат вызова метода такой:
<Клип>.createEmptyMovieClip("<Имя создаваемого клипа>",
<Порядок перекрытия создаваемого клипа>);
Метод createEmptyMovieClip вызывается для того клипа, в который нужно вложить создаваемый "пустой" клип. Оба его параметра нам уже знакомы.
Запишем сценарий с использованием этого метода:
_root.createEmptyMovieClip("tractor", 0);
Этот сценарий поместит на рабочий лист новый "пустой" клип tractor — в компанию к нашему многострадальному автомобилю. Конечно, никакого трактора там пока что нет, но — лиха беда начало…
Удаление клипа
Когда-нибудь нужда в созданных с помощью всех этих действий и методов клипах отпадет, и их придется удалить. Для удаления же клипов предназначено единственное действие removeMovieClip, записываемое в следующем формате:
removeMovieClip(<Удаляемый клип>);
Например, для того чтобы удалить пятое колесо, подойдет такой сценарий:
removeMovieClip(_root.car.wheels);
Обойдемся без запаски — авось гаишник не остановит.
Для удаления клипа можно также воспользоваться методом removeMovieClip объекта movieClip. Формат его вызова очень прост:
<Удаляемый клип>.removeMovieClip();
Внимание!
С помощью действия или метода removeMovieClip можно удалить только те клипы, которые созданы из сценариев. Клипы, созданные в среде Flash, не могут быть удалены таким образом.
Изменение параметров встроенных клипов
Не стоит думать, что Flash может только создавать, дублировать и удалять вложенные клипы. Сейчас мы рассмотрим свойства и методы объекта movieclip, с помощью которых можно изменять различные параметры встроенных клипов: местоположение, размеры и пр.
Так, свойства _х и _у объекта movieclip предоставляют доступ соответственно к горизонтальной и вертикальной координатам клипа. Эти координаты отсчитываются в пикселах от точки отсчета клипа и задаются относительно внешнего клипа, т. е. того, в который текущий клип вложен.
Вот пример сценария, изменяющего координаты "фар" в нашем клипе car:
_root.car._x = 200;
_root.car.headlightl._y = _root.car.headlight2._y + 20;
Свойства _width и _height содержат соответственно ширину и высоту клипа.
Свойства _xscale и _yscale задают процент изменения размеров клипа соответственно по горизонтали и вертикали. Значения, большие 100, заставляют клип увеличить соответствующий размер, а меньшие 100 — уменьшить. Так, если задать для свойства _xscale значение 50, то клип сожмется по горизонтали вдвое.
Свойство _aipha позволяет получить или задать степень прозрачности клипа. Доступны любые целые значения от 0 (полная прозрачность) до 100 (полная непрозрачность).
Свойство _rotation задает угол поворота клипа в градусах. Например:
onClipEvent(enterFrame) {
++this._rotation;
— this._alpha;
}
Этот сценарий заставляет вложенный клип в процессе воспроизведения фильма плавно поворачиваться и одновременно плавно исчезать. Фактически мы можем создавать настоящую анимацию только средствами ActionScript.
Свойство _visible позволяет сделать клип невидимым. Оно имеет логический тип: значение true делает клип видимым, а значение false — невидимым.
onClipEvent(mouseDown) {
this._visible = ~this._visible;
}
Этот сценарий при каждом щелчке по клипу делает его то видимым, то невидимым.
А теперь познакомимся с методами объекта MovieClip, с помощью которых можно изменять порядок перекрытия встроенных клипов.
Метод getDepth возвращает порядок перекрытия текущего клипа. Этот метод не принимает параметров.
Метод getNextHighestDepth возвращает ближайшее верхнее значение уровня перекрытия, еще ничем не занятое. Его можно использовать при создании новых клипов. Например, так:
var clip2 = clipl.duplicateMovieClip("clip2",
_root.getNextHighestDepth());
Это выражение создаст новый клип clip2, продублировав уже имеющийся на рабочем листе клип clip1, и поместит его "над" всеми клипами.
Метод getinstanceAtDepth возвращает ссылку на клип, имеющий заданный порядок перекрытия. Значение порядка перекрытия передается в качестве единственного параметра.
Метод swapDepths меняет значения порядка перекрытия двух клипов местами. Формат его вызова таков:
<Клип 1>.swapDepths("<Клип 2>"|<Порядок перекрытия>);
В качестве параметра этого метода может быть передан путь второго клипа или значение нужного порядка перекрытия. Причем путь второго клипа передается как строка.
Вот три примера использования этого метода:
_root.car.swapDepths("_root.tractor");
_root.car.swapDepths (10);
_root.car.swapDepths(_root.tractor.getDepth());
Получение служебной информации о клипе
Объект MovieClip поддерживает набор особых свойств, доступных только для чтения. Эти свойства возвращают различную служебную информацию, зачастую не относящуюся к самому клипу. Ниже перечислены некоторые из них.
Свойство _name возвращает имя клипа, заданное с помощью панели Properties, в строковом виде.
Свойство _target возвращает полный путь клипа в строковом виде.
Свойства _xmouse и _ymouse возвращают соответственно горизонтальную и вертикальную координаты курсора мыши относительно точки отсчета клипа. Пользуясь этими свойствами, можно контролировать перемещения мыши. Например:
onClipEvent(enterFrame) {
myCursor._x = _root._xmouse;
myCursor._y = _root._ymouse;
}
Этот сценарий заставляет вложенный клип myCursor перемещаться вслед за курсором мыши. Фактически сам клип будет вести себя как курсор мыши.
Свойство _current frame возвращает номер кадра клипа, на котором в данный момент стоит бегунок (фактически номер воспроизводимого в данный момент кадра).
Свойство _totalframes возвращает общее количество кадров, содержащихся во внутренней анимации клипа.
Свойство _url возвращает интернет-адрес, с которого был загружен клип или фильм. Иногда это тоже может пригодиться.
Свойство _framesloaded возвращает количество кадров клипа, данные которых проигрыватель Flash уже загрузил. А методы getBytesLoaded и getBytesTotal помогут узнать соответственно количество загруженных байтов клипа и полный размер клипа в байтах. Используя их, мы можем создавать индикаторы загрузки клипа или фильма.
Реализация drag'n'drop
Термином "drag'n'drop" ("тащи и бросай") обозначают целый набор операций, связанных с перетаскиванием каких-либо объектов операционной системы (файлов, папок, ярлыков), системных или прикладных программ. Так, во Flash с помощью перетаскивания изменяется местоположение фрагментов изображения и бегунка панели Timeline.
Мы также можем реализовать операции "drag'n'drop" в своих фильмах Flash. Сейчас мы выясним, как это сделать.
Первое, что нам понадобится, — это действие startDrag. Оно делает клип доступным для буксировки с помощью мыши. Формат вызова действия такой:
startDrag(<Клип>, [<За центр>, <Х1>, <Y1>, <Х2>, <Y2>]);
В качестве единственного обязательного параметра действию передается путь клипа, который нужно сделать перетаскиваемым. А вот об остальных пяти необязательных параметрах давайте поговорим подробнее.
Второй параметр (за центр) имеет логический тип. Он позволяет указать точку, к которой будет автоматически "приклеиваться" курсор мыши при перетаскивании. Это может быть точка, в которой пользователь щелкнул мышью (значение false), или центр клипа (значение true).
Остальные четыре параметра позволяют описать прямоугольную область, внутри которой можно будет перетаскивать клип и за пределы которой он не сможет выйти. Через параметры X1 и Y1 задаются горизонтальная и вертикальная координаты левого верхнего угла этой области, а за координаты правого нижнего угла "отвечают" параметры Х2 и Y2. Все координаты задаются относительно внешнего клипа.
Вот два примера применения действия startDrag:
startDrag(_root.car);
startDrag(_root.car, true, 100, 100, 500, 500);
Первое выражение просто делает клип перетаскиваемым. При этом пользователь сможет "ухватить" его мышью и перетащить на новое место. Второе же выражение, кроме этого, задает дополнительные параметры перетаскиваемого клипа.
Вместо действия startDrag можно использовать одноименный метод объекта movieClip:
<Kлип>.startDrag([<За центр>, [<Х1>, <Y1>, <Х2>, <Y2>]]);
После вызова действия или метода startDrag клип останется перетаскиваемым на сколь угодно долгое время. Чтобы завершить операцию "drag'n'drop", например, если пользователь отпустит кнопку мыши, нужно вызвать действие или метод stopDrag. Вот так (действие):
stopDrag();
или так (метод):
_root.car.stopDrag();
На заметку
Для завершения операции "drag'n'drop" также можно вызвать еще раз действие или метод startDrag, но уже для другого клипа. Только один клип в данный момент времени может быть перетаскиваемым.
Теперь давайте подумаем, как применить только что полученные сведения в деле написания реальных сценариев-обработчиков событий.
Для запуска и завершения операции "drag'n'drop" можно использовать обработчики событий mouseDown и mouseUp клипа — это очевидно. Давайте напишем эти обработчики и привяжем их к клипу, который нужно сделать перетаскиваемым.
onClipEvent(mouseDown) {
this.startDrag(false);
}
onClipEvent(mouseUp) {
this._x = _root._xmouse;
this._y = _root._ymouse;
this.stopDrag();
}
Обработчик события mouseDown запускает операцию перетаскивания клипа. А обработчик события mouseUp завершает эту операцию и одновременно помещает клип в ту точку, в которой пользователь отпустил кнопку мыши. Как видим, здесь нет ничего сложного.
Объект MovieClip предоставляет доступное только для чтения свойство _droptarget, возвращающее ссылку на так называемую "цель" операции "drag'n'drop" — на клип, в который был "брошен" перетаскиваемый клип. Можно проверить результат, возвращаемый этим свойством, и, в зависимости от него, завершить или не завершить операцию перетаскивания.
Здесь имеет место небольшое затруднение. Дело в том, что свойство _droptarget возвращает результат в особом формате, применяемом в старых версиях Flash (это версии 1–4). Это так называемая "запись со слэшем", когда в качестве разделителя между именем экземпляра объекта и названием его свойства или метода используется косая черта (/), а не точка. Для того чтобы преобразовать "запись со слэшем" в знакомую нам "запись с точкой", нужно воспользоваться встроенной во Flash функцией evai.
Давайте перепишем сценарии-обработчики событий mouseDown и mouseUp так, чтобы они не позволяли пользователю "бросить" перетаскиваемый клип в клип по имени forbiddenArea. Сценарии будут выглядеть так:
onClipEvent(mouseDown) {
this.startDrag(false);
oldX = this._x;
oldY = this._y;
}
onClipEvent(mouseUp) {
if (eval(this._droptarget)!= _root.forbiddenArea) {
this._x = _root._xmouse;
this._y = _root._ymouse;
} else {
this._x = oldX;
this._y = oldY;
}
this.stopDrag();
}
Теперь первый обработчик, помимо запуска операции "drag'n'drop", сохраняет изначальные координаты перетаскиваемого клипа в переменных oldX и oldY. Второй же обработчик, обнаружив, что пользователь перетащил клип в "запрещенное место", восстанавливает изначальное положение перетаскиваемого клипа. В обоих случаях операция "drag'n'drop" завершается.
Так же просто можно написать сценарий, который, наоборот, разрешит "бросать" перетаскиваемый элемент только в одно определенное место. Вообще, можно много чего придумать…
Создание фигурного курсора мыши
Очень многие приложения (не только созданные во Flash, но и обычные, работающие в системе Windows) "щеголяют" фигурными курсорами мыши. Давайте выясним, как создать такой курсор средствами Flash.
Предположим, что мы создали образец-клип и нарисовали в нем курсор желаемой формы. Далее мы поместили экземпляр созданного клипа на рабочий лист и назвали его cursor. Теперь, чтобы превратить этот клип в фигурный курсор мыши, привяжем к нему такой обработчик события по имени load:
onClipEvent(load) {
this.startDrag(true);
}
Обработчик load сразу же после загрузки клипа делает его перетаскиваемым. После этого клип cursor будет всегда перемещаться за курсором мыши и фактически сам станет курсором, чего мы и добивались.
Казалось бы, все замечательно. Одно плохо: "родной" курсор мыши, рисуемый самой системой Windows, портит всю картину. Его нужно спрятать. Для этого воспользуемся методом hide пока еще не изученного нами объекта Mouse (он будет рассмотрен далее в этой главе). Этот метод скрывает системный курсор мыши.
Перепишем обработчик события load. Он будет выглядеть так:
onClipEvent(load) {
Mouse.hide();
this.startDrag(true);
}
Вот теперь все работает, как надо.
Добавим к сказанному, что можно задать область, в которой будет действовать созданный нами фигурный курсор мыши. Для этого достаточно изменить второе выражение приведенного выше обработчика:
this.startDrag(true, 200, 100, 600, 400);
После этого наш фигурный курсор будет "заперт" в указанных границах.
Выявление совпадений и касаний
Часто бывает нужно знать, находится ли заданная точка внутри какого-либо элемента изображения или касаются ли друг друга два элемента. Эта задача — выявление совпадений и касаний — решается в разных случаях по-разному. И, как правило, ее зачастую весьма непростое решение должно быть найдено программистом.
В нашем случае, однако, все намного проще. Разработчики Flash предусмотрели в объекте movieClip особый метод hitTest. С его помощью мы можем проверить, находится ли заданная точка внутри клипа или касаются ли друг друга два отдельных клипа.
Метод hitTest имеет два формата вызова. Первый из этих форматов позволяет выяснить совпадение точки и клипа:
<Клип>.hitTest(<Х>, <Y>, <Проверять контур>);
Понятно, что первые два параметра определяют соответственно горизонтальную и вертикальную координаты нужной нам точки. Третий параметр имеет логический тип и позволяет указать, что считать границами клипа. Если этот параметр имеет значение true, Flash считает границами клипа контур содержащейся в нем графики. В случае значения false Flash "мысленно" вписывает клип в невидимый прямоугольник и считает границами клипа его контур.
Если заданная точка находится внутри клипа, метод hitTest возвращает значение true. В противном случае — значение false. Возвращаемое значение можно использовать в условном выражении или где-либо еще.
Давайте проверим, как работает этот метод. Создадим новый клип, представляющий собой сложную фигуру из множества кривых. Поместим его на рабочий лист и присвоим ему имя hit. После этого привяжем к этому клипу такой обработчик события enterFrame:
onClipEvent(enterFrame) {
if (this.hitTest(_root._xmouse, _root._ymouse, true)) {
this._alpha = 50;
} else { this._alpha = 100;
}
}
Этот сценарий-обработчик события проверяет, находится ли курсор мыши внутри контура нашего клипа. Если это так, клип делается полупрозрачным, в противном случае — полностью непрозрачным (видимым).
В нашем случае метод hitTest проверяет только "попадание" в сам клип, поскольку его третий параметр имеет значение true. Если же передать значение false, то метод станет проверять попадание в воображаемый прямоугольник, описанный вокруг нашего клипа. Это более грубая проверка совпадения точки и клипа.
Второй формат метода hitTest позволит нам проверить на совпадение два различных клипа, т. е. проверить, накладываются они друг на друга или перекрываются:
<Клип!>.hitTest(<Клип 2>);
В этом случае метод hitTest проверяет "попадание" не фигуры в фигуру, а воображаемого прямоугольника, описанного вокруг первой фигуры, в воображаемый прямоугольник, описанный вокруг второй фигуры. Следовательно, метод ведет себя так, словно его в данный момент не существующий третий параметр имеет значение false.
Нам осталось проверить работу метода. Создадим новый образец-клип со сложной фигурой, поместим его экземпляр на рабочий лист, сделаем его поменьше и назовем cursor. К первому (и единственному) кадру фильма привяжем вот такой небольшой сценарий:
_root.cursor.startDrag(true);
Этот сценарий заставляет клип cursor двигаться за мышью, т. е. превращает его в фигурный курсор.
Теперь напишем сценарий-обработчик события enter Frame для клипа hit, так чтобы он проверял касание клипов cursor и hit одного другим:
onClipEvent(enterFrame) {
if (this.hitTest(_root.cursor)) {
this._alpha = 50;
} else { this._alpha = 100;
}
}
Работа с графикой
Хоть Flash и предоставляет мощные средства рисования графики и создания анимации, иногда бывает нужно кое-что дорисовать уже во время воспроизведения фильма. Например, если мы собираемся создать фильм, который в процессе воспроизведения будет выводить на рабочий лист график какой-либо функции, нам потребуются средства для рисования этого самого графика. Что в этом случае может предложить нам Flash?
А предлагает он целый набор методов и свойств объекта MovieClip, служащих для рисования различных линий и заливок. Графика, нарисованная с их помощью, называется созданной программно или просто программной графикой.
В главе 14 мы узнали о маскирующих слоях. Но Flash не останавливается на этом — он позволяет преобразовать в маску любой клип, за исключением, разумеется, внешней анимации.
Программное рисование графики
В этом разделе мы поговорим о том, как выполняется рисование графики из сценариев и какие методы объекта movieClip для этого используются.
Но сначала нужно уяснить два момента.
Во-первых, вся программно нарисованная графика выводится "ниже" нарисованной вручную, т. е. с помощью инструментов рисования Flash. Говорят, что программная графика имеет меньший номер в порядке перекрытия, чем нарисованная вручную. Поэтому перед написанием сценариев, рисующих графику, нужно позаботиться о том, чтобы созданная различными способами графика взаимно не перекрывалась. Рекомендуется выделить для программно рисуемой графики специальные "пустые" клипы, находящиеся на самых верхних слоях.
Во-вторых, как уже говорилось, рисование графики выполняется с помощью специальных методов объекта movieClip. Это значит, что программная графика будет нарисована в том клипе, методы которого мы будем вызывать.
Перейдем к делу.
Для рисования графики из сценариев используется так называемое программное перо (не путать с инструментом рисования "перо"!). С помощью особых методов объекта movieClip это перо можно устанавливать в определенные точки на рабочем листе и проводить им линии, прямые и кривые. Также с помощью программного пера задаются точки, где должны быть помещены заливки.
Для перемещения программного пера в нужную точку рабочего листа используется метод moveTo. Нужно, правда, иметь в виду, что этот метод только перемещает перо, но реально ничего не рисует. Вот формат вызова этого метода:
<Клип>.moveTo(<Х>, <Y>);
Понятно, что в качестве параметров методу передаются горизонтальная и вертикальная координаты точки, в которую нужно переместить программное перо. Эти координаты отсчитываются относительно точки отсчета клипа.
Проще всего программно нарисовать прямую линию, использовав метод lineTo. Он проводит прямую от точки, в которой в данный момент находится программное перо, до точки, чьи координаты переданы в качестве параметров. Вот формат вызова этого метода:
<Клип>.lineTo(<Х>, <Y>);
Как уже говорилось, параметры этого метода есть координаты конечной точки рисуемой прямой. Они отсчитываются от точки отсчета клипа либо от левого верхнего угла, если метод вызван для самого фильма. После рисования прямой линии программное перо останется в ее конечной точке; это позволяет без лишних перемещений нарисовать ломаную или какую-либо геометрическую фигуру.
Вот пример сценария, рисующего в клипе paintBox треугольник:
with (_root.paintBox) {
moveTo(100, 200);
lineTo(300, 200);
lineTo(200, 100);
lineTo (100, 200);
}
Рисование кривых выполняется чуть сложнее. Для этого используется метод curveTo, принимающий четыре параметра:
<Клип>.curveTo(<АХ>, <AY>, <Х>, <Y>);
Параметры Х и Y определяют соответственно горизонтальную и вертикальную координаты конечной точки кривой (начальной же точкой является, опять же, точка, в которой в данный момент находится программное перо). А параметры АХ и AY указывают горизонтальную и вертикальную координаты точки искривления. Все эти координаты отсчитываются, опять же, относительно точки отсчета клипа.
Вот пример сценария, рисующего нечто похожее на окружность:
with (_root.paintBox) {
moveTo(300, 300);
curveTo(400, 300, 400, 200);
curveTo(400, 100, 300, 100);
curveTo(200, 100, 200, 200);
curveTo(200, 300, 300, 300);
}
Увы — более удобных способов программно нарисовать окружность Flash не предлагает. Приходится или создавать образец, рисовать в нем окружность и программно порождать от него экземпляры, или выходить из положения вышеописанным способом. Хотя, можно еще описать окружность в виде функции и нарисовать ее график.
Для рисования линии, неважно — прямой или кривой, будут использованы текущие параметры ее стиля: толщина, цвет и прозрачность. Задание текущего стиля выполняется с помощью метода linestyle. Он вызывается вот так:
<Клип>.lineStyle([<Толщина линии>, [<Цвет линии>,
[<Прозра чность линии>]]]);
Толщина линии задается в пикселах, от 0 до 255. Если она не задана, то линия нарисована не будет. Цвет линии задается в формате 0×RRGGBB, где RR — доля красного цвета, GG — зеленого и ВВ — синего соответственно. Пример задания цвета: 0×22FF44. Прозрачность линии может принимать значения от 0 (полная прозрачность) до 100 (полная непрозрачность).
Важный момент: перед рисованием любой линии лучше с помощью метода linestyle задать ее стиль. Flash сохранит его и сделает текущим; все последующие линии будут нарисованы с использованием текущего стиля.
Поэтому сценарий, рисующий треугольник, нам придется переписать:
with (_root.paintBox) {
lineStyle(2, 0x000000);
moveTo(100, 200);
lineTo (300, 200);
lineTo(200, 100);
lineTo (100, 200);
}
Здесь мы с помощью метода linestyle задали стиль линии: толщина в 2 пиксела и черный цвет. После этого треугольник уж точно будет нарисован.
А теперь давайте посмотрим на только что нарисованный треугольник и подумаем: чего же в нем не хватает? В главе 3 мы выяснили, что, если нарисовать замкнутую фигуру, Flash автоматически создаст заливку; при этом не имеет значения, какой инструмент рисования использовался. Здесь же заливки нет. Почему?
Вероятно, разработчики Flash решили, что, раз уж мы пользуемся сценариями ActionScript, значит, мы достаточно квалифицированные программисты, и нам не нужна помощь. Поэтому нам придется самостоятельно создавать заливку для нарисованных программно фигур.
Для создания заливки служат два метода. Первый из них — beginFill — указывает Flash, что с этого момента нужно отслеживать все операции программного рисования и после создания замкнутой фигуры учесть на будущее, что ей нужна заливка. Второй — endFill — прекращает отслеживание операций рисования и рисует собственно заливку (если, конечно, ее можно нарисовать, т. е. если нарисованный нами контур полностью или частично замкнут).
Формат вызова метода beginFill такой:
<Клип>.beginFill([<Цвет заливки>, [<Прозрачность заливки>]]);
Цвет заливки задается в том же формате 0×RRGGBB, а прозрачность — значением от 0 до 100. Если эти параметры не заданы, будут использованы текущие значения цвета и прозрачности заливки — те, что были указаны при предыдущем вызове метода beginFill. Поэтому при самом первом вызове этого метода нужно указать оба его параметра.
Метод endFill не принимает ни одного параметра:
<Клип>.endFill();
Теперь еще раз перепишем сценарий, чтобы он рисовал треугольник с заливкой:
with (_root.paintBox) {
lineStyle(2, 0×000000);
beginFill(0×222233, 100);
moveTo(100, 200);
lineTo(300, 200);
lineTo (200, 100);
lineTo(100, 200);
endFill ();
}
С помощью метода beginFill создается обычная, сплошная заливка. Если же нужно создать градиентную заливку, то придется воспользоваться методом beginGradientFill в паре с методом endFill. Полное описание этого метода приведено в интерактивной справке Flash.
Чтобы удалить все, что было нарисовано программно, нужно вызвать метод clear:
_root.paintBox.clear();
При этом будет также сброшен заданный с помощью метода linestyie стиль линий. Графика же, нарисованная вручную, удалена не будет.
Пример сценария, рисующего график функции
А теперь давайте попрактикуемся и напишем сценарий, рисующий график функции f(x) = х2. Это, скорее, курьез, чем реально необходимый пример, но он поможет нам глубже изучить методы рисования объекта movieClip.
Сначала создадим новый документ Flash. И привяжем к единственному кадру анимации следующий сценарий:
var dx = 200;
// Величина отступа от левого края рабочего листа
var х = 0;
var у = 0;
// Временные переменные
// Каждая точка графика будет представлять собой небольшой квадрат с
// черной заливкой
lineStyle(1, 0×000000);
// Стиль линий контура этого квадрата
for(х = -20; х < 21; х++) {
// Используем цикл со счетчиком, чтобы вычислить значения функции
// для аргументов в пределах от -20 до 20
у = х * х;
// Вычисляем значение функции
beginFill(0×000000);
// Начинаем рисование заливки квадрата
// Рисуем квадрат
endFill ();
// Заканчиваем рисование заливки
}
Теперь запустим на воспроизведение готовый фильм в отдельном окне. Работает!
Правда, график наш рисуется вверх ногами. Чтобы исправить этот огрех, перепишем наш сценарий. Теперь он будет выглядеть вот так (добавленный и измененный код выделен полужирным шрифтом):
var dx = 200;
dy = 400;
// Величина отступа от верхнего края рабочего листа
var х = 0;
var у = 0;
lineStyle(1, 0×000000);
for(х = -20; х < 21; х++) {
у = х * х;
beginFill(0×000000);
moveTo(dx + х — 1, dy — у + 1);
lineTo(dx + x + 1, dy — у + 1);
lineTo(dx + x + 1, dy — у — 1);
lineTo(dx + х — 1, dy — у — 1);
lineTo(dx + x — 1, dy — у + 1);
endFill ();
}
После этих изменений наш график будет нарисован нормально.
Программное управление масками
А теперь выясним, что можно сделать с масками, используя методы объекта movieClip.
Чтобы маскировать вложенный клип другим клипом (который будет превращен в маскирующий), используется метод setMask:
<Маскируемый клип>.setMask(<Клип-маска>);
Самое интересное заключается в том, что оба клипа совсем не обязательно должны находиться в разных слоях (о слоях см. главу 5, о маскирующих слоях — главу 14). Кроме того, и маскирующий, и маскируемый клипы могут содержать сложную анимацию и даже двигаться. Ух, каких чудес можно натворить!
Давайте создадим новый документ Flash, поместим на рабочий лист клип, содержащий любое растровое изображение, а на него наложим клип с какой-либо простой геометрической фигурой. Назовем нижний клип masked, а верхний — mask. После этого привяжем к единственному кадру анимации такой вот сценарий:
masked.setMask(mask);
mask.startDrag(true);
Первое выражение этого сценария маскирует клип-растровое изображение masked клипом mask. Второе выражение заставляет клип mask (т. е. маску) перемещаться вслед за курсором мыши.
Теперь запустим на воспроизведение созданный фильм в отдельном окне и начнем перемещать курсор мыши с места на место. Забавно получилось, не правда ли?
Кстати, маски, созданные путем вызова метода setMask, имеют приоритет над масками, созданными вручную. Иными словами, если мы создадим маскирующий слой с клипом-маской mask и замаскируем им другой клип masked, то выражение:
mask.setMask(masked);
сделает клип masked маской, а клип mask — маскируемым.
Маскируемый клип в данный момент времени может иметь только одну маску. Так, если для клипа masked вызвать метод setMask еще раз, но передать ему в качестве параметра клип mask2, то он станет новой маской для masked, а предыдущая маска mask "уйдет в отставку".
Чтобы убрать маску совсем, достаточно вызвать метод setMask с параметром null:
masked.setMask(null);
Работа с кнопками
А теперь поговорим о кнопках и работе с ними с помощью сценариев. (Подробнее о кнопках см. главу 18.)
Все находящиеся на рабочем листе кнопки, для которых было задано имя, представляют собой экземпляры объекта Button. Их создает сам Flash; нам же остается только использовать их свойства и методы.
Оператор typeof для кнопки возвращает строку "object" — это значит, что кнопка относится к объектному типу данных.
Свойства и методы объекта Button
По своим свойствам и методам объект Button во многом похож на объект movieclip. Имея весьма схожие наборы свойств и методов, эти два объекта зачастую ведут себя одинаково. В частности, объект Button поддерживает свойства х, _у, _xmouse, _ymouse, _height, _width, _alpha и _rotation, уже знакомые нам по объекту movieClip. Однако объект Button не поддерживает методы play, stop, gotoAndPiay, gotoAndStop и подобные им, так как назначение его все же иное, чем у объекта movieclip. Так что кнопку можно рассматривать как очень специализированный, "урезанный" вариант клипа.
Рассмотрим специфические свойства объекта Button, которые обязательно пригодятся нам в работе с его экземплярами. (Кстати, многие из этих свойств поддерживаются и объектом movieclip, но редко используются в клипах.)
Свойство enabled позволяет разрешить или запретить пользователю нажимать кнопку. Оно имеет логический тип: значение true разрешает доступ к кнопке, а значение false — запрещает.
Свойство _visibie позволяет сделать кнопку видимой или невидимой. Оно имеет логический тип: значение true делает кнопку видимой, а значение false — невидимой. При этом невидимая кнопка также недоступна для нажатия.
Свойство useHandCursor задает, какую форму примет курсор мыши, если поместить его над кнопкой. Если задано значение true, то отображается курсор в виде "указующего перста" (как над гиперссылкой). Если же задано значение false, то курсор имеет вид обычной стрелки.
Известно, что обычные кнопки в окнах Windows-приложений можно нажимать, не только щелкая по ним мышью, но и нажимая клавишу <Space> основной клавиатуры. Для этого кнопка должна иметь фокус ввода, который даст ей возможность принимать нажатия клавиш клавиатуры. Кнопка, имеющая фокус ввода, выделяется точечным прямоугольником, окружающим ее надпись.
Фокус ввода можно перемещать с одной кнопки на другую, согласно особой последовательности, называемой порядком обхода. Каждая кнопка имеет свой уникальный номер в этом порядке. Для перехода на элемент управления с большим номером в порядке обхода нужно нажать клавишу <Таb>, для перехода на элемент управления с меньшим номером — комбинацию клавиш <Shift>+<Tab>.
Для задания порядка обхода кнопок Flash служат два свойства объекта Button. Рассмотрим их.
Свойство tabindex задает номер в порядке обхода для данной кнопки. Значением этого свойства может быть любое целое неотрицательное число.
Задать порядок обхода можно с помощью приведенного ниже сценария, привязанного к первому кадру анимации фильма:
btnForward.tabindex = 0;
btnBackard.tabindex = 1;
btnStop.tabindex = 2;
Также для этого можно воспользоваться панелью Accessibility, подробно описанной в главе 20.
Если ни для одной кнопки в фильме Flash не задан номер в порядке обхода (т. е. значение свойства tabindex равно undefined), Flash будет применять порядок обхода по умолчанию, и кнопки будут "обходиться" по нажатию клавиши <Таb> в том порядке, в котором они были созданы на рабочем листе. Также нужно иметь в виду, что значение undefined меньше любого числового, поэтому кнопки, для которых свойство tabindex не было задано, будут в порядке обхода первыми.
Свойство tabEnabied позволяет вообще убрать кнопку из порядка обхода, после чего ей нельзя будет дать фокус ввода с помощью клавиатуры (хотя нажимать ее щелчком мыши будет можно). Это свойство имеет логический тип: значение true или undefined предоставляет возможность дать кнопке фокус ввода с помощью клавиатуры, а значение false такую возможность отменяет.
Обработка событий, возникающих в кнопках
Сценарий-обработчик события, возникающего в кнопке, как мы помним из главы 18, имеет такой формат записи:
on(<Событие>) {
<Тело обработчика>
}
Например:
on (press) {
_root.stop();
}
В данном примере обработчик выполняется в ответ на нажатие кнопки и останавливает анимацию основного фильма. Код этого обработчика должен быть привязан к самой кнопке.
Все события, поддерживаемые объектом Button, перечислены в табл. 19.11.
Создание и удаление кнопок из сценариев
Ранее в этой главе мы говорили, что имеется возможность создавать и удалять клипы из сценариев, пользуясь соответственно методами attachMovie и removeMovieClip объекта movieclip и аналогичными действиями. Такая возможность реализована и для кнопок. Так, мы можем создать на рабочем листе новую кнопку в процессе воспроизведения фильма, привязав к кадру анимации такой сценарий:
_root.attachMovie("button", "button2", 1);
А затем мы можем удалить эту кнопку:
_root.button2.removeMovieClip();
Работа с текстовыми блоками
Текстовые блоки, описанные в главе 7, служат для отображения текста. Они бывают трех видов:
□ статические текстовые блоки, служащие для отображения текста, который не изменяется в процессе воспроизведения фильма или работы Flash-приложения. Это могут быть надписи, заголовки, инструкции и пр.;
□ поля ввода, служащие для ввода текста пользователем;
□ динамические текстовые блоки, служащие для вывода текста, который изменяется в процессе воспроизведения фильма или работы Flash-приложения. Это может быть, например, текст, содержащий результаты работы приложения.
Flash поддерживает полноценную работу только с полями ввода и динамическими текстовыми блоками (как мы знаем из главы 7, они называются специальными текстовыми блоками). Именно средства для работы с ними мы сейчас рассмотрим. Средства для доступа к содержимому статических текстовых блоков весьма ограничены; все они описаны в интерактивной справке Flash.
Объект TextField и его свойства и методы
И поля ввода, и динамические текстовые блоки представляются одинаково — как экземпляры объекта TextField. Они также создаются самим Flash для каждого поля ввода или динамического текстового блока, помещенного на рабочий лист и имеющего имя.
Оператор typeof для специального текстового блока возвращает строку "object", т. е. специальный текстовый блок имеет объектный тип данных.
Объект TextField имеет множество свойств и методов. Мы опишем только некоторые из них; полное описание этого объекта приведено в интерактивной справке Flash.
Прежде всего, объект Text Field поддерживает свойства _х, _у, _xmouse, _ymouse, _height, _width, _alpha и _rotation, знакомые нам по объекту movieclip. Кроме того, он обладает свойствами enabled, _visible, tabEnabled и tablndex, которые поддерживаются также объектом Button.
Да-да, как и в случае кнопок, мы можем назначать для полей ввода номера в порядке обхода с помощью сценария вида:
txtNamel.tablndex = 0;
txtName2.tablndex = 1;
txtEmail.tablndex = 2;
btnOK.tablndex = 3;
btnCancel.tablndex = 4;
или панели Accessibility (см. главу 20).
Свойство type объекта Text Field служит для задания вида данного экземпляра объекта Text Field, т. е. определяет, будет это поле ввода или динамический текстовый блок. Это свойство имеет строковый тип: значение "input" превращает экземпляр объекта Text Fie id в поле ввода, а значение "dynamic" — в динамический текстовый блок. Свойство доступно как для чтения, так и для записи, а это значит, что мы можем превращать поля ввода в динамические текстовые блоки и наоборот.
Свойство text позволяет получить или задать текст, находящийся в поле ввода или динамическом текстовом блоке. Оно имеет строковый тип.
Пример выражения со свойством text:
txtName.text = "Vasya Pupkin";
Нужно только помнить, что это свойство возвращает текст без тегов HTML, если таковые в нем присутствовали.
Свойство variable позволяет задать переменную, с которой будут связаны поле ввода или динамический текстовый блок. Свойство имеет строковый тип. Задав переменную, мы сможем получать и задавать содержимое поля ввода или текстового блока, просто обратившись к этой переменной:
var name: String = "";
txtName.variable = "name";
name = "Vasya Pupkin";
Свойство html позволяет разрешить или запретить вводить в поле ввода или динамический текстовый блок текст, отформатированный с помощью тегов HTML. Оно имеет логический тип: значение true разрешает вводить HTML-текст, а значение false — запрещает.
Свойство htmlText используется для получения или задания значения поля ввода или динамического текстового блока в том случае, если ввод HTML-текста разрешен.
txtName.html = true;
txtName.htmiText = "<B>Vasya</B> <I>Pupkin</I>";
Подробнее о поддержке тегов HTML в текстовых блоках рассказано в интерактивной справке Flash.
Свойство maxChars позволяет задать максимальное количество символов, которое может быть введено в поле ввода пользователем. (Количество символов, помещаемое в это поле ввода из сценариев, в любом случае не ограничено.) Это свойство принимает неотрицательные числовые значения; значение null отменяет ограничение на количество вводимых символов.
Доступное только для чтения свойство length возвращает количество символов, введенное в поле ввода.
Свойство multiline имеет логический тип и позволяет сделать поле ввода или динамический текстовый блок многострочным. Для этого достаточно присвоить этому свойству значение true. А присвоение значения false вновь делает поле ввода или динамический текстовый блок однострочным.
Свойство password позволяет превратить обычное поле ввода в поле ввода пароля. Для этого достаточно присвоить этому свойству логическое значение true. Присвоение значения false вновь делает поле ввода обычным.
Свойство selectable позволяет сделать поле ввода или динамический текстовый блок выделяемым; при этом пользователь сможет выделять текст, находящийся в данном поле или текстовом блоке, и копировать его в буфер обмена Windows. Это свойство имеет логический тип: значение true разрешает пользователю выделять текст, а значение false — запрещает.
Свойство wordwrap используется в том случае, если необходимо, чтобы текст в поле ввода или динамическом текстовом блоке переносился по строкам. Оно имеет логический тип: значение true устанавливает автоматический перенос строк текста, значение false его отменяет.
Помимо описанных, объект Text Field поддерживает несколько свойств, задающих форматирование текста. Все эти свойства перечислены в табл. 19.12.
Обработка событий, возникающих в текстовых блоках
Обработка событий, возникающих в текстовых блоках, выполняется не так, как в клипах и кнопках. Специфика заключается в том, что к текстовому блоку невозможно привязать сценарий. Поэтому нам придется пойти другим путем.
Давайте для примера создадим обработчик события, возникающего при изменении содержимого поля ввода. Для этого напишем функцию, содержащую код этого обработчика:
function txtNameChanged() {
needToSave = true;
}
Пусть она просто присваивает логической переменной needToSave значение true. Впоследствии мы можем использовать это значение, чтобы проверить, изменил ли пользователь какие-то данные в поле ввода.
Мы только что создали функцию-обработчик события. Ее следует поместить в сценарий, привязанный к первому кадру анимации основного фильма, чтобы Flash сразу же ее прочитал.
Да, но как собственно привязать ее к текстовому блоку? Очень просто. Объект TextField поддерживает набор свойств, соответствующих поддерживаемым им событиям. Мы просто присвоим написанную нами функцию нужному свойству, вот так:
_root.txtName.onChanged = txtNameChanged;
Да, такие "фокусы" считаются стандартными в языке ActionScript! А свойство onChanged, соответствующее событию, происходящему при изменении содержимого поля ввода, получит тип данных "функция".
На заметку
Оператор typeof при передаче ему в качестве параметра функции или переменной, которой присвоена функция, вернет строку "function".
Всего объект TextField поддерживает четыре события. Связанные с ними свойства, которым нужно присвоить соответствующую функцию-обработчик, перечислены в табл. 19.13.
На заметку
Свойства, соответствующие событиям, поддерживают также объекты movieClip и Button. Их описание можно найти в интерактивной справке Flash.
Использование перехватчиков событий
Мы уже знаем два способа обработки событий. Первый способ — это использование для написания сценариев-обработчиков событий специальных действий (onClipEvent и on). Второй способ — это присвоение соответствующему свойству функции, которая будет вызываться в ответ на это событие и, таким образом, станет его обработчиком. Первый способ компактнее, но работает не для всех объектов, второй же не столь компактен, но зато универсален (именно с его помощью обрабатываются события в текстовых блоках).
Однако Flash предоставляет нам еще один способ обработки нужного события — с использованием так называемого перехватчика событий (в терминологии Flash — "listener", "слушатель"). Это экземпляр объекта object, содержащий особые свойства, соответствующие обрабатываемым им событиям. Этим свойствам присваиваются функции-обработчики соответствующих событий, после чего перехватчик особым образом привязывается к экземпляру объекта, события которого нужно обработать.
В случае текстового блока с помощью перехватчика могут быть обработаны события onchanged и onScroller. (Это значит, что перехватчик должен содержать свойства onchanged и onScroller.) Вот пример сценария, создающего такой перехватчик (предположим, что функции обработки нажатия клавиш fOnChanged и fOnScroller уже описаны):
myListener = new Object ();
myListener.onchanged = fOnChanged;
myListener.onScroller = fOnScroller;
Изначально объект object не содержит свойств onchanged и onScroller. Они будут созданы в экземпляре этого объекта myListener, который мы только что создали, и будут "принадлежать" только этому экземпляру.
Для привязки перехватчика к текстовому блоку используется метод addListener объекта Text Field. Этот метод принимает единственный параметр — ссылку на перехватчик.
txtName.addListener(myListener);
Это выражение привязывает созданный нами перехватчик к полю ввода txtName.
Один и тот же перехватчик можно привязать сразу к нескольким текстовым блокам:
txtName2.addListener(myListener);
txtFamily.addListener(myListener);
Это значит, что события, происходящие в разных текстовых блоках, можно обрабатывать с помощью одного комплекта функций-обработчиков. Иногда это бывает полезно, особенно если обработчики, привязанные к разным текстовым блокам, делают одно и то же.
Чтобы "отвязать" от текстового блока ненужный более перехватчик, воспользуемся методом removeListener. Этот метод в качестве единственного параметра также принимает ссылку на перехватчик.
txtName.removeListener(myListener);
Теперь останется только совсем удалить ненужный перехватчик:
delete myListener;
Создание и удаление текстовых блоков из сценариев
Flash также позволяет создавать и удалять текстовые блоки с помощью особых сценариев. Сейчас мы выясним, как это делается.
Для создания поля ввода или динамического текстового блока используется метод createTextField объекта movieClip. Формат его вызова таков:
<Клип>.createTextField(<Имя>, <Порядок перекрытия>, <Х>, <Y>,
<Ширина>, <Высота>);
Первый параметр задает имя создаваемого поля ввода или динамического текстового блока в строковом виде, а второй — его порядок перекрытия. Третий и четвертый параметры задают соответственно горизонтальную и вертикальную координаты верхнего левого угла создаваемого текстового блока относительно клипа, в котором он создается. Последние два параметра задают размеры — ширину и высоту — текстового блока. И координаты, и размеры задаются в пикселах.
Нужно помнить, что с помощью этого метода создается динамический текстовый блок, т. е. свойство type соответствующего экземпляра объекта TextField сразу же получит значение "dynamic". Чтобы преобразовать этот экземпляр в поле ввода, нужно присвоить свойству type строку "input". Например:
_root.createTextField("txtName", 0, 100, 100, 200, 50);
_root.txtName.type = "input";
_root.txtName.variable = "Name";
Этот сценарий создает поле ввода txtName и привязывает его к переменной Name.
Для удаления созданного с помощью метода createTextField текстового блока используется метод removeTextField объекта TextField:
_root.txtName.removeTextField();
Внимание!
С помощью действия или метода removeText Field можно удалить только те текстовые блоки, которые созданы из сценариев. Текстовые блоки, созданные вручную, не могут быть удалены таким образом.
Использование объекта Selection
Flash также предоставляет возможность управления текстовым курсором и выделением текста в текстовых блоках. Для этого предназначен объект selection, единственный экземпляр которого по имени selection создается самим Flash.
Метод get Focus этого объекта возвращает в строковом виде имя переменной, привязанной к текстовому блоку, имеющему в данный момент фокус ввода. Если к текстовому блоку не привязана переменная или если фокус ввода имеет кнопка или клип, то возвращается путь (также в строковом виде). Если ни один текстовый блок, ни одна кнопка и ни один клип не имеют фокуса, возвращается значение null.
Для того чтобы дать какому-либо текстовому блоку (а также кнопке или клипу) фокус ввода, нужно вызвать метод set Focus. В качестве единственного параметра этому методу передается путь в строковом виде:
Selection.setFocus("_root.txtName");
Selection.setFocus("_root.btnOK");
Чтобы снять фокус ввода со всех элементов управления, достаточно передать методу setFocus в качестве параметра значение null.
С помощью объекта selection мы можем получить позицию текстового курсора в поле ввода. Для этого достаточно вызвать не принимающий параметров метод get Caret index, который вернет нам номер символа, на котором стоит курсор. (Не стоит забывать, что нумерация символов начинается с нуля.) Если же ни одно поле ввода не имеет фокуса, возвращается значение — 1.
Методы getBeginindex и getEndindex возвращают номера соответственно начального и конечного символа выделенного в текстовом блоке фрагмента текста. Если ничего не выделено, также возвращается значение — 1.
Можно выделить нужный фрагмент текста, воспользовавшись методом setSelection. Первый параметр этого метода должен иметь значение, равное номеру первого символа выделяемого фрагмента, а второй параметр — значение, равное номеру последнего символа. Вот так:
Selection.setSelection(10, 30);
Чтобы просто поставить текстовый курсор в требуемую позицию, нужно передать методу setSelection номер нужного символа и в первом, и во втором параметре:
Selection.setSelection(10, 10);
Объект selection поддерживает одно-единственное событие onSetFocus, возникающее при перемещении фокуса ввода. Обработка этого события возможна только с помощью перехватчика. Например:
myListener = new Object ();
myListener.onSetFocus = fOnSetFocus;
Selection.addListener(myListener);
Это пример создания и привязки перехватчика к объекту selection. Функция fOnsetFocus выполняет собственно обработку события onset Focus; определение этой функции было опущено.
Обработка нажатий клавиш клавиатуры
Для обработки нажатия клавиш клавиатуры служит объект Key. Его единственный экземпляр, также носящий имя Key, создается самим Flash.
Свойства и методы объекта Key
Два важнейших метода, которые обязательно понадобятся нам для обработки нажатий клавиш, — это методы getAscii и getcode. Первый метод возвращает код символа ASCII, который присвоен нажатой клавише. Второй метод возвращает так называемый виртуальный код нажатой клавиши — низкоуровневый код, позволяющий узнать, какая клавиша на клавиатуре была нажата. Оба эти метода не принимают параметров.
Вот пример выражений вызова этих методов:
codel = Key.getAscii(); code2 = Key.getCode();
Код символа ASCII зависит от текущей кодировки. Коды символов кодировки Windows 1251 приведены в интерактивной справке Flash; там же приведены и виртуальные коды клавиш.
Еще один полезный метод объекта Key — метод isDown. Он принимает единственный параметр — виртуальный код клавиши — и возвращает значение true, если эта клавиша нажата. Например:
if (Key.isDown(Key.ENTER)) {. }
Приведенное выше выражение проверяет, была ли нажата клавиша <Enter>.
Метод isToggied возвращает значение true, если в момент его вызова была включена одна из клавиш-переключателей: <NumLock> или <CapsLock>. Он принимает единственный параметр — числовое значение 20 (виртуальный код клавиши <CapsLock>) или 144 (виртуальный код клавиши <NumLock>).
Пример вызова метода isToggied:
if (Key.isToggied(20)) { s = s.toLowerCase; }
Кроме вышеописанных методов, объект Key поддерживает ряд свойств, доступных только для чтения и возвращающих значения виртуальных кодов различных служебных клавиш клавиатуры. Все эти свойства приведены в табл. 19.14.
Обработка нажатий клавиш в клипах
А теперь поговорим о том, как же собственно выполняется обработка нажатий клавиш клавиатуры. Выполнить ее можно двумя способами, которые мы и рассмотрим в этом разделе.
Обработка нажатий клавиш в клипах
Первый — более простой — способ обработки нажатий клавиш — заключается в привязке к клипу, который будет реагировать на нажатия, обработчика события keyDown, возникающего при нажатии клавиши. Мы рассмотрим создание этого обработчика на примере.
Создадим новый документ Flash. В нем создадим образец-клип, содержащий простую геометрическую фигуру, например, круг. Поместим экземпляр этого образца на рабочий лист и назовем его circle. Этот экземпляр мы заставим перемещаться по листу в ответ на нажатия клавиш — стрелок.
Теперь выделим наш экземпляр и привяжем к нему довольно сложный сценарий, содержащий обработчики сразу двух событий. Для удобства рассмотрим их отдельно друг от друга.
onClipEvent(load) {
d = 1;
}
Обработчик события load помещает значение в переменную d сразу после загрузки клипа. Эта переменная задает величину перемещения нашего экземпляра при нажатии любой клавиши-стрелки. Можно задать и большее число, чтобы заставить клип двигаться быстрее.
Второй фрагмент сценария выглядит более сложным:
onClipEvent(keyDown) {
switch (Key.getCode()) {
case Key.UP:
_root.circle._y — = d;
break;
case Key.DOWN:
_root.circle._y += d;
break;
case Key.LEFT:
_root.circle._x — = d;
break;
case Key.RIGHT:
_root.circle._x += d;
break;
}
}
Но, несмотря на кажущуюся сложность, этот обработчик события keyDown довольно-таки прост. Он сравнивает значение виртуального кода нажатой клавиши с кодами клавиш-стрелок и, если одна из них нажата, изменяет соответствующую координату клипа circle.
Теперь запустим созданный фильм на воспроизведение в отдельном окне. Он работает!
Конечно, наш пример очень прост. Тем не менее, руководствуясь им, можно создавать и несравнимо более сложные вещи. Например — как насчет игры "15", реализованной на Flash? Или всем известного "Сапера"?
Обработка нажатий клавиш с помощью перехватчика
Второй способ обработать нажатия клавиш — использовать перехватчик. Этот перехватчик должен иметь свойства onKeyUp и onKeyDown, которым должны быть присвоены функции, обрабатывающие соответствующие события. Событие onKeyDown возникает при нажатии клавиши, а событие onKeyUp — при ее отпускании.
Давайте перепишем созданный ранее сценарий так, чтобы он использовал обработчик. В данном случае он будет привязан не к клипу, а к первому кадру анимации фильма.
Рассмотрим этот сценарий по частям.
Сначала:
var d = 1;
Это уже знакомая нам переменная, задающая величину смещения клипа за один шаг.
А дальше:
function fOnKeyDown() {
switch (Key.getCode()) {
case Key.UP:
_root.circle._y — = d;
break;
case Key.DOWN:
_root.circle._y += d;
break;
case Key.LEFT:
_root.circle._x — = d;
break;
case Key.RIGHT:
_root.circle._x += d;
break;
}
}
А это объявление функции, обрабатывающей событие onKeyDown. Ее код практически совпадает с кодом обработчика события keyDown для клипа, написанного нами ранее.
И, наконец:
var myListener = new Object ();
myListener.onKeyDown = fOnKeyDown;
Key.addListener(myListener);
Этот фрагмент кода создает и привязывает к объекту Key перехватчик. Собственно, это тоже нам знакомо.
Взаимодействие с мышью
Для взаимодействия с мышью служит объект Mouse. Единственный экземпляр этого объекта под именем Mouse создается самим Flash.
Прежде всего, этот объект предоставляет методы hide и show. Первый метод скрывает курсор мыши, а второй — вновь выводит его на экран. Ни один из них не принимает параметров. Эти методы используются, как правило, при создании фигурных курсоров мыши.
Объект Mouse поддерживает также три события:
□ событие onMouseDown возникает при нажатии левой кнопки мыши;
□ событие onMouseUp возникает при отпускании левой кнопки мыши;
□ событие onMouseMove возникает при любом перемещении мыши;
□ событие onMouseWheel возникает при прокрутке колесика мыши, если такое имеется.
Для обработки этих событий используются перехватчики. Все функции, обрабатывающие их, не принимают параметров, за исключением функции-обработчика события onMouseWheel. Она имеет такой формат:
function <Имя>([<Смещение>, <Клип, над которым находится курсор мыши>])
Первый из необязательных параметров этой функции определяет смещение, на которое пользователь прокрутил колесико мыши. Оно передается в числовом виде в так называемых "тиках". Второй параметр передает ссылку на клип, над которым находился курсор мыши во время прокрутки ее колесика.
Для отслеживания координат мыши можно использовать свойства _xmouse и _ymouse объекта movieClip. Этот "нужный экземпляр" может быть как внешней анимацией (_root), так и каким-либо вложенным клипом. Эти же свойства поддерживаются и объектом Button.
Управление звуковым сопровождением фильма
Для управления звуковым сопровождением фильма служат экземпляры объекта sound. (О работе со звуком во Flash см. главу 17.) Эти экземпляры создаются с помощью выражений, имеющих следующий формат:
<Переменная> = new Sound([<Клип, звуковым сопровождением которого нужно <управлять>]);
С единственным параметром этому конструктору передается ссылка на клип, звуковым сопровождением которого мы собираемся управлять. Если этот параметр не указан, создается экземпляр объекта, управляющий звуковым сопровождением всего фильма.
Вот два примера создания разных экземпляров объекта sound:
carSound = new Sound(car);
globalSound = new Sound();
Экземпляр carSound позволяет управлять звуковым сопровождением клипа саг, а экземпляр globalSound — всего фильма.
Объект sound имеет множество свойств и методов. В этом разделе мы рассмотрим некоторые из них.
Метод start запускает воспроизведение звука. Он имеет следующий формат вызова:
<Экземпляр объекта Sound>.start([<Отметка>, <Количество повторов>]);
Этот метод может принимать два необязательных параметра. Первый параметр указывает, с какой отметки начнет воспроизводиться звук; отметка задается как количество секунд, которые Flash отсчитает с момента начала звука. Со вторым параметром передается количество повторов звука. Если ни один параметр не задан, звуковое сопровождение будет воспроизведено один раз с самого начала.
Например, выражение
carSound.start (10, 2);
запускает воспроизведение звука, привязанного к клипу car, с десятисекундной отметки и воспроизводит его два раза.
Метод stop немедленно останавливает воспроизведение звука. Формат его вызова таков:
<Экземпляр объекта Sound>.stop([<Идентификатор образца-звука>]);
В качестве единственного параметра этого метода может быть передано идентификатор сценарного образца-звука, воспроизведение экземпляра которого нужно остановить, в строковом виде. Если метод был вызван без параметра, останавливается воспроизведение всех звуков.
carSound.stop("engineSound");
Это выражение отключает воспроизведение звука engineSound, привязанного к клипу car.
Не принимающий параметров метод getVolume возвращает значение громкости звука. А метод setVolume позволяет задать новое значение громкости звука, переданное в качестве его единственного параметра. Доступны значения от 0 (звук не слышен) до 100 (полная громкость; значение по умолчанию).
carSound.setVolume(mySound.getVolume() + 10);
Это выражение увеличивает громкость работы автомобиля на десять единиц.
Пара методов get Pan и set Pan ведут себя так же и позволяют задать панорамирование звука в пространстве. Здесь доступны значения от -100 (звук в левом канале) до 100 (звук в правом канале); значение по умолчанию — 0 (звук "посередине").
carSound.setPan(50);
Объект sound также поддерживает два свойства, доступные только для чтения. Свойство position возвращает текущую воспроизводимую позицию звука в миллисекундах. А свойство duration возвращает общую продолжительность звука, также в миллисекундах.
Использование таймеров
Во многих случаях нужно выполнять какое-либо действие через равные промежутки времени. Это может понадобиться, например, для создания анимации с помощью сценариев ActionScript или для обновления информации, взятой с удаленного сервера. Для таких задач во Flash предусмотрены таймеры. Поговорим о них.
Таймер создается с помощью действия setinterval. Оно имеет два формата вызова. Вот первый из них:
<Переменная> = setinterval(<Функция>, <Значение интервала>
[, <Список параметров функции, разделенных запятыми>]);
Здесь в качестве параметров передается функция, которая будет вызываться по истечении интервала времени, и само значение этого интервала в миллисекундах. Также в выражении вызова могут присутствовать необязательные параметры, задающие значения параметров вызываемой функции; их должно быть столько, сколько параметров принимает эта функция.
А вот второй формат вызова действия setinterval:
<Переменная> = setintervai(<Экземпляр объекта>, <Метод объекта>,
<Значение интервала>
[, <Список параметров метода, разделенных запятыми>]);
Он отличается тем, что вместо функции здесь передается экземпляр какого-либо объекта и его метод.
В любом случае действие setinterval возвращает особый идентификатор таймера, который в дальнейшем будет использован для его уничтожения.
Приведем примеры выражений, создающих таймеры:
timerlDl = setintervai(tick, 1000);
timerID2 = setintervai(car, moveBy, 100, d);
Первое выражение создает таймер, вызывающий функцию tick каждую секунду (1000 миллисекунд). Второе же создает таймер, вызывающий каждые 100 миллисекунд метод moveBy экземпляра объекта car и передающий ему параметр d. Разумеется, и функция tick, и метод moveBy должны быть объявлены прежде, чем будут использованы.
При использовании таймеров нужно иметь в виду следующее. Дело в том, что Flash отмеряет интервалы не очень точно. Он пытается привязать каждый интервал к частоте кадров фильма, если, конечно, это возможно. Если интервал меньше частоты кадров, то он обрабатывается с максимальной точностью, и код вызывается вовремя. Если же интервал больше частоты кадров, то код, связанный с таймером, исполняется только тогда, когда Flash воспроизводит очередной кадр фильма. Это сделано для того, чтобы лишний раз не перерисовывать экран, если код что-то изменит в изображении.
Если же нужно обновить экран прямо сейчас, следует вызвать не принимающее параметров действие updateAfterEvent. Оно часто используется при выполнении сценариев, изменяющих содержимое рабочего листа.
После того как нужда в таймере отпадет, его следует уничтожить, чтобы освободить системные ресурсы. Для этого используется действие clearinterval, которое имеет такой формат вызова:
clearinterval(<Идентификатор таймера>);
Например:
clearinterval(timerID2);
А теперь рассмотрим пример, показывающий, как можно использовать таймер для создания так называемого "ленивого" курсора мыши. Обычный курсор мыши нигде надолго не задерживается — он спешит за ней сразу после малейшего ее перемещения. "Ленивый" же курсор отличается от обычного тем, что никогда не торопится за мышью. Давайте же сделаем такой курсор.
Прежде всего, создадим новый образец-клип и нарисуем в нем желаемый курсор. Постараемся нарисовать его так, чтобы точка отсчета пришлась как раз на "острие" этого курсора. Поместим экземпляр этого образца-клипа на рабочий лист и назовем его cursor.
Теперь напишем код сценария, который будет привязан к первому кадру фильма. Давайте рассмотрим его по частям.
function tick() {
if (_root.cursor._x!= _root._xmouse) {
if (_root.cursor._x < _root._xmouse) {
if (_root._xmouse — _root.cursor._x < d) {
_root.cursor._x = _root._xmouse;
} else {
_root.cursor._x += d;
}
} else {
if (_root.cursor._x — _root._xmouse < d) {
_root.cursor._x = _root._xmouse;
} else {
_root.cursor._x — = d;
}
}
}
if (_root.cursor._y!= _root._ymouse) {
if (_root.cursor._y < _root._ymouse) {
if (_root._ymouse — _root.cursor._y < d) {
_root.cursor._y = _root._ymouse;
} else {
_root.cursor._y += d;
}
} else {
if (_root.cursor._y — _root._ymouse < d) {
_root.cursor._y = _root._ymouse;
} else {
_root.cursor._у — = d;
}
}
}
updateAfterEvent();
}
Мы объявили функцию, реализующую перемещение "ленивого" курсора. Она сравнивает координаты, горизонтальную и вертикальную, курсора и мыши и выполняет приращение координат курсора. Нужно отметить, что координаты мыши при этом отсчитываются относительно анимации основного фильма.
Продолжаем писать наш сценарий:
d = 25;
Это величина приращения, на которое будут изменяться координаты курсора. И далее:
ctID = setlnterval(tick, 50);
Здесь мы создаем таймер, вызывающий функцию tick каждые 50 миллисекунд.
И, наконец:
_root.onUnload = function() {
clearinterval(ctID);
}
А здесь мы привязываем к событию unload клипа cursor обработчик, удаляющий созданный ранее таймер. Удалять за собой затребованные для своих нужд ресурсы, те же таймеры, — хороший стиль программирования.
Если уж зашла речь о таймерах, то нам может пригодиться функция getTimer. Она возвращает количество миллисекунд, прошедших с момента, когда фильм начал воспроизводиться.
Загрузка внешних файлов
Ранее в этой главе уже упоминалось о том, что язык ActionScript позволяет загрузить и поместить в фильм Flash внешний файл. Этим внешним файлом может быть другой фильм Shockwave/Flash, изображение в формате JPEG, видео Macromedia Flash Video или звук. Также имеется возможность открыть Web-обозреватель и загрузить в него какую-либо Web-страницу. Настала пора выяснить, как это делается.
Загрузка и выгрузка фильмов Shockwave/Flash и изображений в формате JPEG
Проще всего загрузить в основной фильм, воспроизводящийся в окне проигрывателя Flash, другой фильм Shockwave/Flash или изображение в формате JPEG из внешнего файла (загружаемого фильма). Такое часто делается, особенно при создании Web-сайтов, целиком основанных на Flash.
Вложение загружаемого фильма или изображения в основной фильм
Проще всего создать на рабочем листе "пустой" клип (например, с помощью метода createEmptyMovieClip, описанного ранее в этой главе) и заменить его загружаемым фильмом. При этом загружаемый фильм вкладывается в основной, становясь его составной частью.
Для загрузки фильма Shockwave/Flash или изображения JPEG из внешнего файла используется действие loadMovie, которое вызывается так:
loadMovie("<Интернет-адрес внешнего файла>",
<Путь заменяемого клипа>);
Примеры использования действия loadMovie:
loadMovie("/books/32501/OEBPS/truckWheel.swf", _root.car.wheel2);
loadMovie(sURL, _root.car);
Также можно воспользоваться методом loadMovie объекта movieClip. Формат его вызова почти такой же, как у одноименного действия:
<Заменяемый клип>.loadMovie("<Интернет-адрес внешнего файла>");
Пример использования этого метода:
_root.car.wheel2.loadMovie("/books/32501/OEBPS/truckWheel.swf");
Здесь мы загружаем фильм truckWheel.swf и заменяем им второе колесо нашего автомобиля.
А теперь предположим, что фильм truckWheel.swf из вышеприведенного примера содержит в себе сценарий:
_root.stop();
останавливающий воспроизведение его анимации (вращение колеса). Если открыть этот фильм в проигрывателе Flash, то сценарий выполнится правильно. Но если загрузить фильм truckWheel.swf в другой (основной) фильм, как мы это только что сделали, этот сценарий остановит анимацию не колеса автомобиля, а основного фильма. Ведь модификатор _root всегда возвращает ссылку на внешнюю анимацию, и в нашем случае он вернет ссылку на основной фильм, поскольку фильм truckWheel.swf стал его составной частью.
Что делать? Как нам заставить этот сценарий вложенного фильма выполняться корректно в любом случае? Очень просто: нужно привязать к первому кадру фильма truckWheel.swf вот такой совсем небольшой сценарий:
this._lockroot = true;
Здесь мы присвоили свойству _lockroot объекта movieClip, обозначающего сам фильм, значение true. После этого модификатор _root в любом сценарии, содержащемся в загружаемом фильме, всегда будет возвращать ссылку на внешнюю анимацию именно этого фильма — truckWheel.swf, даже если мы вложим его в другой фильм.
После того как нужда в загруженном из внешнего файла фильме или изображении пропадет, самое время его выгрузить. Зачем это нужно? Хотя бы затем, чтобы освободить ресурсы компьютера пользователя для других, более важных задач. Именно для этого язык ActionScript предоставляет действие unloadMovie, выгружающее из памяти и удаляющее с экрана ранее загруженный фильм. Формат вызова этого действия такой:
unloadMovie(<Путь выгружаемого клипа или изображения>);
Пример:
unloadMovie(_root.car.engine);
В этом выражении мы избавляемся от двигателя нашего автомобиля — зачем он нужен, раз автомобиль все равно не двигается с места.
А вот это выражение выгрузит сам основной фильм:
unloadMovie(_level0._root);
после чего проигрыватель Flash, оставшись не у дел, автоматически завершит свою работу.
Перекрывающиеся фильмы
Только что мы выяснили, как вложить загружаемый фильм в основной. Но Flash предоставляет также возможность наложить содержимое внешнего файла на содержимое основного фильма так, чтобы они перекрывали друг друга, полностью или частично. В таком случае эти фильмы не вкладываются друг в друга (подобно вложенным клипам), а остаются полностью независимыми. Такие фильмы называются перекрывающимися, а само это явление — перекрытием фильмов.
Зачем может понадобиться перекрытие фильмов? А, например, для создания Web-сайтов, основанных на Flash. В этом случае сначала загружается и выводится на экран "объединяющий" фильм, содержащий заголовок сайта, полосу навигации и какой-то изначальный текст. При щелчке на какой-либо кнопке полосы навигации особый сценарий загружает фильм с соответствующим содержимым и выводит его на экран как перекрывающийся клип, перекрывая изначальное содержимое. Схема достаточно простая и наглядная; удивительно только, почему таких сайтов все еще довольно мало.
В главе 4, описывающей трансформации, давалось понятие порядка перекрытия фрагментов графики друг относительно друга (его еще называют z-координатой). В случае с перекрывающимися фильмами используется примерно такое же понятие, только называемое по-другому, а именно — уровень фильма. Отсчет уровней ведется, начиная с самого нижнего клипа (фильма) до самого верхнего. Фильмы с большим номером уровня находятся "выше" фильмов с меньшим номером и перекрывают их.
На этом сходство с порядком перекрытия исчерпывается, и начинаются отличия. Их три.
Во-первых, самым "нижним" всегда является фильм, изначально воспроизводящийся в проигрывателе Flash, — он имеет уровень 0. Все остальные фильмы, которые будут загружены как перекрывающиеся, находятся "выше" него, т. е. имеют более высокий уровень — 1, 2 и т. д.
Во-вторых, для обозначения уровня фильма используются не числа, а особые модификаторы, в состав которых входят номера уровней. Они возвращают ссылку на внешнюю анимацию соответствующего фильма и имеют вид _level<номер уровня>. Самый "нижний" фильм имеет модификатор _level0. Более "высокие" фильмы имеют модификаторы _level1, _level2 и т. д.
Мы можем использовать эти модификаторы для доступа к перекрывающимся фильмам. Например:
_level0.gotoAndPlay(1);
_levell.car.wheel.stop();
Внимание!
Перед тем как обратиться к перекрывающемуся фильму, находящемуся на каком-то уровне, нужно сначала его туда загрузить. Как это сделать, будет рассказано чуть позже.
В-третьих, мы можем загрузить какой-либо фильм на уровень, на котором уже имеется другой фильм. В этом случае загружаемый фильм заменит тот, что раньше был на этом уровне. Можно загрузить какой-либо фильм и на уровень 0 — в этом случае он заменит фильм, изначально загруженный в проигрыватель Flash.
Для загрузки перекрывающегося фильма используется действие loadMovieNum, аналогичное действию loadMovie. Формат его вызова таков:
loadMovieNum("<Интернет-адрес загружаемого файла>", <Уровень>);
Приведем два примера выражений, использующих действие loadMovieNum:
loadMovieNum("/videos/driving.swf", 0);
loadMovieNum("/books/32501/OEBPS/ads/banner45.jpg", 2);
Первое выражение заменяет основной фильм фильмом driving.swf. Второе же выражение загружает рекламный баннер и помещает его над основным фильмом. (Непонятно, правда, зачем это нужно делать. Если только для испытания нервов зрителей.)
Для выгрузки перекрывающегося фильма используется действие unloadMovieClip. Вот формат его вызова:
unloadMovieNum (<Уровень выгружаемого клипа или изображения>);
Пример:
unloadMovieNum(_level2);
Это выражение убирает назойливо маячивший перед глазами рекламный баннер.
Загрузка звуков
Для загрузки звука из внешнего файла в формате MP3 (другие форматы не поддерживаются) следует воспользоваться методом loadSound объекта Sound. Вот формат его вызова:
<Звук>.loadSound(<Интернет-адрес или путь внешнего звукового файла>,<Потоковый звук>);
Первый параметр задает интернет-адрес звукового файла или его путь на локальном диске компьютера в строковом виде. Второй параметр — логический — задает, будет ли загружаемый звук потоковым (значение true) или звуком-сигналом (значение false). (О потоковых звуках и сигналах см. главу 17.)
Вот пример сценария, загружающего звуковой файл с использованием метода loadSound:
newSound = new Sound();
newSound.loadSound("sounds/background_music.mp3", true);
newSound.play();
Объект Sound поддерживает событие onLoad, возникающее по окончании загрузки звука. Это событие можно обработать с помощью функции-обработчика, принимающей единственный параметр. Если звук был успешно загружен, этот параметр примет логическое значение true. Соответственно, если проигрыватель Flash почему-то не смог загрузить этот звук, обработчику передается значение false.
Вот пример функции-обработчика события onLoad:
function onNewSoundLoad(success) {
if (success) {
newSound.play();
}
}
newSound.onLoad = onNewSoundLoad;
Файлы формата MP3, кроме собственно звука, могут хранить дополнительные данные — так называемые теги MP3. В этих тегах записываются, в частности, имя исполнителя, название альбома и песни, год выпуска, жанр и пр. Для доступа к этим тегам служит свойство ID3 объекта Sound. Оно возвращает ссылку на экземпляр объекта Object, свойства которого и содержат информацию о различных тегах MP3. Эти свойства возвращают, в частности:
□ свойство ТСОМ — имя исполнителя;
□ свойство TALB — название альбома;
□ свойство TIT2 — название произведения;
□ свойство ТСОМ — жанр произведения;
□ свойство TYER — год выпуска альбома;
□ свойство TIME — продолжительность произведения;
□ свойство TRCK — номер произведения в альбоме.
Объект Sound поддерживает также методы getBytesLoaded и getBytesTotal, возвращающие соответственно размер загруженной части звукового файла в байтах и общий размер загружаемого звука в байтах.
Загрузка видео
Теперь рассмотрим процесс загрузки и воспроизведения внешних видеофайлов формата Macromedia Flash Video (другие форматы не поддерживаются). Подробно об этом формате было рассказано в главе 16.
Все находящиеся на рабочем листе экземпляры образцов-импортированных клипов, для которых было задано имя, представляют собой экземпляры объекта Video. Их создает сам Flash; нам же остается только использовать их свойства и методы.
Объект Video поддерживает метод attachVideo, выполняющий загрузку внешнего видеофайла и воспроизведение его в экземпляре образца-импортированного видео. Для загрузки и воспроизведения лучше всего использовать "пустой" видеоклип, процесс создания которого мы сейчас рассмотрим.
Итак, чтобы загрузить и воспроизвести внешний видеоклип, нужно сначала создать на рабочем листе "пустой" экземпляр объекта Video. Для этого откроем панель Library и выберем в ее дополнительном меню пункт New Video. В списке панели Library появится новый пункт с именем вида Embedded Video <порядковый номер>. Дважды щелкнем на этом имени, введем в появившееся поле ввода новое, более вразумительное имя и нажмем клавишу <Enter>. Поместим на рабочий лист экземпляр этого образца и дадим ему какое-нибудь имя, например, vidExternal. Все — "пустой" видеоклип создан.
Теперь привяжем к первому кадру анимации такой сценарий:
var nc = new NetConnection();
nc.connect(null);
var ns = new NetStream(nc);
vidExternai.attachVideo(ns);
ns.play("videos/introduction.flv");
Здесь мы используем для загрузки внешнего видеофайла экземпляры объектов NetConnection и NetScream. Подробное описание этих объектов можно найти в интерактивной справке Flash.
Загрузка Web-страниц
Напоследок мы рассмотрим используемый во Flash способ загрузки в окно Web-обозревателя какой-либо Web-страницы. Для этого предназначено действие getURL, формат вызова которого таков:
getURL ("<Интернет-адрес Web-страницы>" [, "<Цель>"]);
С первым параметром этого действия передается сам интернет-адрес загружаемой Web-страницы. Через второй, необязательный, параметр задается цель гиперссылки. Параметр цель имеет строковый тип и может принимать следующие значения:
□ "_blank" — Web-страница загрузится в отдельное окно Web-обозревателя;
□ "_parent" — Web-страница загрузится в родительский набор фреймов;
□ "_seif" — Web-страница загрузится в текущий фрейм (это значение параметра по умолчанию);
□ "_top" — Web-страница загрузится в текущее окно Web-обозревателя, заменив собой весь набор фреймов, если он есть.
Кроме того, можно передать со вторым параметром имя фрейма, в который должна быть загружена эта страница.
Вот пример сценария, привязанного к кнопке и загружающего Web-страницу сайта Macromedia в отдельное окно Web-обозревателя:
on (click) {
getURL("http://www.macromedia.com", "_blank");
}
Ограничения на доступ к внешним файлам
Интернет — небезопасное место. Вирусы, "троянские программы", мошеннические сайты — всего этого добра там более чем достаточно. И неудивительно, что создатели программ, работающих с Интернетом, встраивают в них различные средства, призванные хоть как-то обеспечить безопасность пользователя и его данных. Пусть даже ценой каких-то ограничений.
Не стал исключением и наш любимый Flash. Всеобщая озабоченность безопасностью (вполне, кстати, оправданная) отразилась и на нем. Разработчики фирмы Macromedia предусмотрели для своего детища множество ограничений на работу с внешними файлами. Рассмотрим эти ограничения.
Нужно сказать сразу, что внешние файлы во Flash можно загружать с любого интернет-адреса. Они будут нормально отображаться в окне проигрывателя Flash. Но если мы попытаемся получить доступ к экземплярам объектов, функциям или переменным, находящимся во внешнем файле, Flash сразу даст нам по рукам. Смотреть, дескать, смотрите, но руками не троньте!
Какие же внешние файлы можно "трогать руками"? Какие ограничения Flash накладывает на доступ к внешним файлам? А вот какие…
Прежде всего, файлы, которые желают "общаться" друг с другом на уровне сценариев, должны быть загружены с одного и того же Web-сервера. А именно, если они были загружены с Web-сервера, имеющего IР-адрес 192.168.1.10, то они смогут обращаться к объектам, функциям и переменным друг друга. То же самое справедливо для файлов, загруженных с сервера . Однако если файлы были загружены с серверов и , то они не смогут "общаться" друг с другом на уровне сценариев.
Еще одно ограничение связано с протоколами HTTP (HyperText Transport Protocol, транспортный протокол передачи гипертекста) и HTTPS (HyperText Transport Protocol Secured, защищенный транспортный протокол передачи гипертекста). (Протокол — это набор правил, согласно которым программы обмениваются данными по сети.) Если основной фильм был загружен по протоколу HTTP, а внешний — по протоколу HTTPS (или наоборот), то они не смогут получить доступ друг к другу через сценарии.
В предыдущей версии Flash (MX) описанные ограничения были непреодолимыми. Во Flash MX 2004 появилась возможность их преодолеть. Сейчас мы выясним, как это делается.
Пусть мы загрузили основной фильм с сервера . И пусть нам понадобилось загрузить с сервера внешний файл car.swf, поместить его на рабочий лист, а впоследствии иметь к нему доступ через сценарии. Для этого нам нужно будет использовать метод allowDomain объекта security, находящегося в объекте System. Формат его вызова таков:
System, security. allowDomain ("<Разрешенный интернет-адреc>");
В качестве единственного параметра этого метода передается интернет-адрес Web-сервера, с которого разрешена загрузка внешних файлов. После этого все файлы, загруженные с этого сервера, доступны из текущего фильма через сценарии.
В нашем случае нам нужно поместить в первый кадр анимации файла car.swf такой сценарий:
System.security.allowDomain("http://www.somesite.ru");
после чего все сценарии основного фильма, обращающиеся к файлу car.swf, будут работать.
Если основной фильм был загружен по протоколу HTTP, а внешний файл car.swf — по протоколу HTTPS, нам следует использовать метод allowinsecureDomain того же объекта. Формат вызова этого метода совпадает с форматом вызова метода allowDomain. А код необходимого сценария должен быть таким:
System.security.allowInsecureDomain("https://secured.somesite.ru");
_root.placeholder.loadMovie("https://secured.somesite.ru/car.swf");
Осталось заметить, что все вышесказанное относится только к файлам Shockwave/Flash. Для файлов Macromedia Flash Video и MP3 все это неактуально, так как они не содержат ни объектов, ни функций, не переменных, к которым можно получить доступ.
Работа с внешними данными
Загрузка и отображение на рабочем листе содержимого внешних файлов — это только часть возможностей, предлагаемых Flash для общения с внешним электронным миром. Другая, весьма обширная, часть позволяет получать и обрабатывать данные, поставляемые так называемыми серверными программами — программами, работающими совместно с Web-сервером. Сейчас мы об этом поговорим.
Отправка данных серверной программе
Предположим, мы создали несколько полей ввода, собирающих данные от пользователя. Как теперь отправить эти данные серверной программе?
Прежде всего, их нужно поместить в переменные. Причем это должны быть переменные уровня клипа, т. е. не локальные и не глобальные. И еще: серверной программе отправляются сразу все данные, находящиеся во всех объявленных в клипе переменных. Так что нужно стараться не создавать лишних переменных уровня клипа.
Для посылки данных нам следует использовать уже изученные методы и действия, а именно:
□ getURL — загрузка Web-страницы;
□ loadMovie и loadMovieNum — загрузка внешнего клипа;
□ loadSound — загрузка внешнего звука.
Поскольку серверная программа — это обычный файл, находящийся на диске компьютера, на котором работает Web-сервер (как и Web-страница), формат вызова всех этих действий и методов не изменится. Есть, правда, единственное исключение, о котором мы сейчас поговорим.
Все перечисленные действия и методы поддерживают еще один необязательный параметр. Он передается самым последним в списке параметров, имеет строковый тип и определяет способ передачи данных, описывающий то, как данные кодируются перед передачей и как затем передаются. Какой способ выбрать, зависит от серверной программы, с которой мы собираемся "общаться".
Первый способ передачи данных называется get. При его использовании данные передаются Web-обозревателем Web-серверу как часть интернет-адреса. Чтобы передать данные этим способом, нам нужно будет передать с последним параметром описанным выше действиям и методам значение GET.
Например, пусть у нас имеется набор переменных, содержащих имя и пароль пользователя в строковом формате (они могут быть, скажем, введены этим самым пользователем в поля ввода):
name1 = Ivan
name2 = Ivanov
password = vanyusha
Тогда, чтобы отправить серверной программе program.exe, находящейся по адресу http://www.site.ru/bin/, эти данные методом get, мы напишем такое выражение:
getURL("http://www.site.ru/bin/program.exe", "_blank", "GET");
Обратим внимание на последний параметр этого метода. В нем передается строка "GET" — знак того, что данные должны быть переданы методом GET.
В результате Flash отправит Web-cepeepy следующий адрес (сами данные в нем выделены полужирным шрифтом):
http://www.site.ru/bin/program.exe?name1=Ivan&&name2=Ivanov&password=vanyusha
Как видим, пересылаемые способом GET данные объединяются в пары "переменная" = "значение", помещаются в самый конец интернет-адреса и отделяются от него вопросительным знаком. При этом одна пара от другой отделяется знаком "коммерческое и" (&). Все это достаточно просто и наглядно.
Получив этот запрос, Web-cepeep первым делом отделит отправленные данные от собственно интернет-адреса серверной программы (в нашем случае это program.exe). Далее он запустит саму эту программу (если она еще не запущена) и передаст ей данные.
Второй способ носит название POST. Данные с его помощью передаются также парами "переменная" = "значение", но уже не в виде части интернет-адреса, а в виде так называемых дополнительных данных запроса. Опять же, Web-сервер выделит эти данные и передаст их серверной программе.
Чтобы реализовать способ POST, нам нужно будет передать соответствующему действию или методу с последним параметром строку "POST":
_root.loadMovie("http://www.site.ru/bin/getswf.exe", "POST");
Это выражение выполнит отправку данных способом post. В результате его выполнения серверная программа вернет файл Shockwave/Flash, содержащий клип, который заменит в окне проигрывателя Flash основной фильм.
Все эти методы и действия хороши, пока нам не понадобится получить от серверной программы результат обработки переданных нами данных. В этом случае нам придется воспользоваться другими действиями и методами, которые будут описаны ниже.
Получение данных от серверной программы
Самый простой способ передать серверной программе данные и сразу же получить от нее результат их обработки — использовать действие loadVariabies или одноименный метод объекта movieClip. Это действие (метод) отправляет данные серверной программе и сразу же начинает ожидать получения результата. В принципе, с его помощью мы можем заставить приложение Flash загружать данные из текстового файла, находящегося на сервере или даже на диске нашего собственного компьютера.
Нужно сразу сказать, что серверная программа должна отправить данные, полученные в результате обработки, в виде строки, содержащей набор пар "переменная" = "значение", отделенных друг от друга знаком & (так же кодируются данные, передаваемые способом GET). Только тогда действие (метод) loadVariabies сможет правильно их обработать.
Получив от серверной программы данные, действие (метод) loadVariabies создает в указанном нами клипе соответствующие переменные, если они еще не созданы, и присваивает им принятые значения.
Формат вызова действия loadVariabies таков:
loadVariabies("Интернет-адрес серверной программы",
Путь клипа, получающего данные"[, "GET|POST"]);
С первым параметром передается интернет-адрес серверной программы, которая должна получить данные и отправить результат, или текстового файла, содержащего их. Со вторым параметром передается путь клипа, который должен принять и обработать эти данные. Третий, необязательный, параметр используется для задания способа передачи отправляемых данных.
Примеры использования действия loadVariabies:
loadVariabies("", _root.dataHandler,"POST");
loadVariabies("data.txt", _root.dataHandler);
Оба эти выражения загружают полученные данные в клип dataHandler. Но только первое выражение получает их от серверной программы, передав ей способом POST значения переменных уровня клипа, а второе загружает их из текстового файла.
Метод loadVariabies вызывается почти так же:
<Клип, получаюпщй данные>.loadvariabies("Интернет-адрес серверной программы" [, "GET | POST"]);
Например:
_root.dataHandler.loadvariabies("", "POST");
Для загрузки данных в перекрывающийся фильм используется действие loadVariablesNum. Вот формат его вызова
loadvariabies("Интернет-адрес серверной программы",
"Уровень перекрытия фильма, принимающего данные"[, "GET|POST"]);
Комментарии, как говорится, излишни.
Вроде бы, все просто — выполняем действие или метод, получаем данные и обрабатываем их в своем приложении. Просто, да не совсем. Давайте рассмотрим небольшой сценарий, принимающий от серверной программы значение переменной frameNumber:
_root.loadVariables("");
_root.gotoAndStop(frameNumber);
Будет ли работать этот код? Может, будет, а может, и нет. И вот почему…
Когда мы даем приложению Flash команду получить данные от серверной программы или из текстового файла, мы не можем быть уверены в том, что эти данные будут получены сию же секунду. Более того, вообще нельзя быть уверенным, что Flash сможет получить их в течение какого-то строго определенного промежутка времени. Это может произойти как через долю секунды, так и через час (например, если произошел обрыв связи или если серверная программа перегружена другими запросами). И когда именно Flash получит результат, мы предугадать не можем.
Но если мы не можем предсказать время, в течение которого приложение получит внешние данные, то мы можем отследить сам момент их получения. Для этого достаточно обработать событие data объекта movieClip, возникающее после получения клипом всех (до самой последней переменной) данных.
С учетом сказанного перепишем приведенный выше сценарий:
_root.onData = function() {
_root.gotoAndStop(frameNumber);
}
_root.loadVariables("");
Вот теперь он будет работать.
Использование объекта LoadVars
Существует другой способ получения данных от серверной программы — использование экземпляров объекта LoadVars. Этот объект предоставляет по сравнению с действиями loadVariable и loadVariableNum возможность несколько более строгого контроля над процессом обмена данными, хотя выполняет те же самые функции.
Прежде всего, нам нужно создать экземпляр объекта LoadVars:
myLoadVars = new LoadVars();
Затем мы просто создаем для него новые свойства, чьи имена совпадают с именами переменных, которые нужно передать серверной программе.
И разумеется, присваиваем этим свойствам нужные значения:
myLoadVars.namel = "Ivan";
myLoadVars.name2 = "Ivanov";
myLoadVars.password = "vanyusha";
Чтобы отправить данные серверной программе, используется метод send. Формат его вызова таков:
<Экземпляр объекта LoadVars>.send("<Интернет-адрес серверной программы>"[, "<Цель>", "GET|POST"]);
С первым параметром передается интернет-адрес серверной программы, которой посылаются эти данные. Со вторым параметром может быть передана цель, указывающая, куда будет выведен результат обработки этих данных (как правило, это Web-страница, сгенерированная серверным приложением). Третий необязательный параметр определяет способ отправки данных; если он не указан, выбирается способ POST.
Вот пример выражения, реализующего отправку данных с помощью экземпляра объекта LoadVars:
myLoadVars.send("", "_blank", "GET");
Для приема данных от серверной программы используется метод load. С единственным параметром этого метода передается интернет-адрес этой серверной программы или же путь к текстовому файлу, содержащему нужные данные. Что касается данных, то они, опять же, должны быть представлены в виде текстовой строки, состоящей из пар "переменная" — "значение", отделенных друг от друга знаком &.
Вот пример использования метода load:
myLoadVars.load("");
Метод sendAndLoad одновременно отправляет серверной программе данные и получает от нее результат их обработки. Формат вызова этого метода:
<Экземпляр объекта LoadVars, отправляющий данные>. sendAndLoad ("<Интернет-адрес серверной прогрраммы>",
<Экземпляр объекта LoadVars, принимающий данные> [, "GET | POST"]);
Этот метод вызывается для того экземпляра объекта LoadVars, который должен отправить данные. С первым параметром передается интернет-адрес серверной программы, которая должна их получить, со вторым — ссылка на экземпляр объекта LoadVars, который получит результат. Третий параметр определяет способ отправки данных; если он не указан, выбирается способ POST.
Например:
mySendVars.sendAndLoad("", myLoadVars);
Для того чтобы узнать, получены ли данные, нужно обработать событие load объекта LoadVars, возникающее после получения всех данных. Функция-обработчик этого события должна принимать один логический параметр, обозначающий, успешно ли получены данные (значение true) или нет (false).
Вот пример функции-обработчика этого события:
myLoadVars.onLoad = function(isSucceed) {
if (isSucceed) {
_root.gotoAndStop(frameNumber);
}
}
Свойство loaded объекта LoadVars возвращает значение true, если данные были успешно получены, и false в противном случае. Если операция приема данных не была запущена, возвращается значение undefined.
Объект LoadVars предоставляет также еще два метода, которые можно использовать для отображения процесса загрузки данных. Метод getBytesLoaded возвращает количество загруженных байт данных. А метод getBytesTotal возвращает общий объем загружаемых данных в байтах. Оба эти метода возвращают значение undefined, если операция загрузки данных не была запущена или еще реально не началась. Метод getBytesTotal также возвращает значение undefined, если Web-сервер, под управлением которого работает серверная программа, не сообщил размер передаваемых данных.
Что дальше?
Вот и закончилась третья часть этой книги, посвященная Flash-программированию. Конечно, многое осталось нерассмотренным, но ведь эта книга посвящена графике и анимации, а для интересующихся ванием во Flash существуют другие книги и интерактивная справка, в которой описано абсолютно все.
Следующая глава будет посвящена оптимизации готовых изображений и фильмов перед их публикацией в формат Shockwave/Flash. Она совсем короткая.