Московский физико-технический институт
Опубликован: 23.12.2005 | Доступ: свободный | Студентов: 2869 / 253 | Оценка: 4.61 / 4.44 | Длительность: 27:18:00
ISBN: 978-5-9556-0051-2
Лекция 14:

Работа флэш-программ в Internet

Загрузка дополнительных роликов

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

А иногда бывает очень удобно загрузить внешний ролик целиком. Это может понадобиться для совершенно разных вещей, например, для создания сложных предзагрузчиков, которые мы рассмотрим далее в этой лекции. В качестве другого примера использования загрузки внешних роликов можно привести флэш-оболочку для просмотра нескольких более-менее однородных роликов.

Как загрузить внешний ролик

Во Flash MX применяются два похожих способа загрузки роликов: loadMovie и loadMovieNum.

Метод loadMovie предназначен для загрузки внешнего ролика внутрь клипа. Синтаксис его такой:

<MovieClip>.loadMovie (url [,variables]);

Здесь url - это URL, откуда флэш-плеер может скачать *.swf-файл с загружаемым роликом (это может быть, например, относительный URL-путь к файлу, лежащему рядом, или обращение к web-серверу по HTTP).

Variables - необязательный параметр, обозначающий способ отправки переменных (" GET " или " POST ") на сервер, его следует указывать, если действительно нужно отправить все переменные из клипа, у которого вызван метод, на web-сервер. Нельзя отправить какую-то одну переменную, отправлены будут непременно все (доступные для перебора for...in ) значения переменных из данного клипа. Отправка переменных происходит в виде url-кодированной строки (см. предыдущий параграф).

Следить за процессом загрузки ролика можно, используя методы класса MovieClip getBytesLoaded(), getBytesTotal() и его же свойства _framesloaded и _totalframes. То есть вы можете сравнивать количество загруженных байтов или кадров с их полным количеством и делать отсюда соответствующие выводы. Остается лишь понять, когда именно вызывать вышеописанные функции (или просматривать содержимое свойств). Делать это в каждом кадре не оптимально. К счастью, существует событие класса MovieClip под названием onData. Подписавшись на это событие (то есть, определив в вашем классе или объекте функцию с именем onData ) вы сможете узнавать о том, что пришла очередная порция данных загружаемого ролика.

Парный метод для loadMovie - unloadMovie, с помощью которого можно выгрузить ролик из клипа. После выгрузки клип становится абсолютно пустым, независимо от того, что в нем было раньше.

Аналогичные действия можно выполнить при помощи глобальной функции loadMovie, которая имеет синтаксис:

loadMovie(url, target [, variables]);

В этом случае клип, в который происходит загрузка, указывается в параметре target в виде строчки, описывающей путь к нему. В этом случае, как мы уже говорили, описывая свойство _target, точки заменяются слэшами. Например, клип _level1.car.wheel следует описывать как " _level1/car/wheel ". Разница по сравнению с методом MovieClip.loadMovie состоит в том, что переменные на сервер посылаются из того клипа, в кадре которого была вызвана функция (а не из клипа, в который происходит загрузка нового ролика).

Рассмотрим теперь второй способ загрузки внешних роликов.

Глобальная функция loadMovieNum позволяет загрузить внешний ролик в уровень (level) флэш-плеера.

Напомним, что во флэш-плеере можно использовать произвольное количество уровней, каждый из которых определяет свое дерево владения клипов. Первый уровень называется _level0, он же _root, если ролик загружен "естественным" образом (флэш-плеером, а не с помощью loadMovie или loadMovieNum ).

Не путайте эти уровни ( level ) с уровнями depth в клипах, которые используются для правильного расположения клипов по z-оси, это немного другое понятие, хоть уровни level тоже влияют на вертикальное расположение, но не клипов, а роликов. На определенный уровень depth в клипе можно динамически поместить объект с помощью attachMovie, в уровень же level можно загрузить только целый ролик.

Вернемся к функции loadMovieNum. Ее синтаксис таков:

loadMovieNum (url, level [,variables]);

Параметры url и variables имеют здесь то же назначение, что и в loadMovie, а level - это номер уровня ( level ), в который нужно загрузить внешний ролик. Парный метод loadMovieNum - unloadMovieNum. Если вы укажете значение параметра variables (разрешены значения " GET " или " POST "), то на сервер будут отправлены все видимые переменные, которые имеются в клипе, из кадра коего вызвана функция.

В целом loadMovieNum работает абсолютно аналогично loadMovie, какой из них использовать в конкретном случае - решать вам. Хочется отметить одно интересное свойство loadMovieNum: переменные _levelN (за исключением _level0 ) до применения loadMovieNum не определены, но после загрузки в соответствующий уровень ( level ) ролика они становятся доступны для использования.

Наконец, упомянем про ряд особенностей работы рассмотренных здесь функций. (Часть из этих особенностей присуща и функции getURL и уже обсуждалась в связи с ее работой.) Особенность первая: запросы оптимизируются, то есть если не нужно посылать ни одной переменной, то пойдет запрос типа GET независимо от того, что вы указали. Особенность вторая: если вы вызываете метод MovieClip.loadMovie, то нужно, чтобы ваш клип был корректно встроен в дерево клипов (например, с помощью attachMovie, регистрации классов и пр.), а не просто создан с помощью new. В противном случае метод сработает так, как будто он вызван у того клипа, в кадре которого написан код. Особенность третья: для глобальной функции loadMovie путь к клипу, в который будет происходить загрузка ролика, обязательно должен быть корректным (вести к существующему клипу), иначе функция loadMovie вовсе не сработает. (Нужно заметить, что пути наподобие " _level1 ", " _level2 " и т.п. считаются корректными даже в том случае, когда в соответствующие уровни еще не загружены ролики.) Вышеописанное поведение, кстати, отличается от того случая, когда клип указан корректно, а вот с сервера никакого ролика, который должен быть в него загружен, не присылается. В этом случае предыдущее содержимое клипа все равно будет выгружено из него...

_root, _level и динамическая загрузка роликов

Если вы используете loadMovie или loadMovieNum, вас могут подстерегать проблемы.

Представьте себе, что у вас есть ролик myMovie, в котором лежит текстовое поле textField, а в первом кадре написан такой код:

_level0.textField.text = "my text";

Эта программа, разумеется, выводит в текстовом поле " my text ".

Попробуем сделать загрузчик для такого ролика.

Сделаем новый флэш-ролик и в первом его кадре напишем:

loadMovieNum ("myMovie.swf", 1);

Как вы думаете, что выведет такая программа? Ничего.

В чем же дело? Если вы немного позанимаетесь отладкой, то обнаружите, что объекта " _level0.textField " нет. Дело в том, что при написании ролика myMovie вы предполагали, что _level0 - это именно то место, в котором лежит текстовое поле, а оказывается - нет. Теперь "то самое место" - это _level1, в который мы загрузили ролик myMovie.

Наш совет: не используйте без особой надобности переменные _levelN. Во Flash MX специально существует "относительная" переменная _root, которая всегда указывает на относительный корень дерева владения клипов.

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

Обсудим еще один вопрос.

Что произойдет, если загрузить ролик непосредственно в _level0? Это можно сделать, например, так: loadMovieNum (url, 0) или _level0.loadMovie (url).

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

Загружаем переменные аналогично роликам

Во Флэш МХ существует несколько функций, предназначенных для загрузки переменных с сервера. Вот те из них, которые аналогичны функциям загрузки роликов.

<MovieClip>.loadVariables (url [,variables]);
loadVariables (url, target [, variables]);
loadVariablesNum (url, level [, variables]);

Как вы видите, их синтаксис полностью аналогичен синтаксису метода MovieClip.loadMovie и глобальных функций loadMovie и loadMovieNum, о которых мы писали ранее. И работают эти функции вы также совершенно аналогично. Единственная разница - что загружают в соответствующие клипы или уровни не ролики, а переменные.

Тонкости, связанные с оптимизацией запроса (заменой POST на GET, если не посылаются переменные), встраиванием клипа в дерево (для метода MovieClip.loadMovie ) и неверным указанием адреса загрузки (функция вовсе не срабатывает) остаются в точности такими же при загрузке переменных, как и при загрузке клипов.

А что происходит с уже имеющимися в клипе переменными при загрузке переменных туда? Абсолютно то же самое, что и при попытке "вручную" записать туда переменные с такими же значениями. То есть если переменных не было - они создаются, если были - их значения меняются (но лишь в том случае, когда эти переменные не защищены от записи).

Но как же узнать, что все переменные загрузились? Подпишите клип, в который приходят переменные, на событие onData (создайте в нем функцию с таким именем). На всякий случай (если вы ожидаете большой объем данных, который может придти несколькими порциями) можете устроить так, чтобы в самом конце списка переменных сервер присылал вам переменную endOfLoading со значением true. И по событию onData проверять, установилось ли endOfLoading в true, или еще нет.