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

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

Предзагрузчики

Первое, что приходит в голову, когда речь идет о загрузке флэш-роликов через Интернет, - это вопрос "сколько ролик будет загружаться и сколько этого придется ждать пользователю?". Одно из лучших решений этой проблемы - показать пользователю красивую картинку "Loading..." (возможно, с какой-то "легкой" анимацией) и предоставить информацию о том, сколько процентов основного ролика уже загружено. Для этого и предназначены предзагрузчики ( preloaders ).

Как сделать простой предзагрузчик

Что нужно для того, чтобы сделать предзагрузчик? Две вещи:

  • механизм, позволяющий узнать, какой процент ролика уже загрузился;
  • механизм, позволяющий организовать ожидание, пока не загрузился весь ролик.

По поводу первого механизма, здесь есть два варианта:

  1. можно использовать свойства MovieClip _framesloaded и _totalframes ;
  2. можно использовать методы MovieClip getBytesLoaded() и getBytesTotal().

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

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

Пример.

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

Поместите в первый кадр слоя Actions такой код:

textField.text = "Loading: " + _framesloaded / _totalframes;

А во второй кадр слоя Actions - такой:

if ((_framesloaded / _totalframes) < 1) gotoAndPlay (1);

Вот и весь предзагрузчик. Как только отношение _framesloaded / _totalframes достигнет 1, мы выйдем из цикла и перейдем к основной анимации, расположенной дальше второго кадра.

Отметим еще раз, что, используя _framesloaded, _totalframes, getBytesLoaded() и getBytesTotal(), можно также следить за процессом загрузки роликов, загружаемых через loadMovie. Как мы уже говорили раньше, это никак не относится к runtime-shared символам, о процессе загрузки которых ничего узнать нельзя.

Не забывайте также, что если вы поставите у символа библиотеки галочку Export in first frame в параметрах символа (которую обязательно нужно поставить, если вы хотите динамически создавать экземпляры этого символа с помощью attachMovie() ), он будет загружен в самом первом фрейме, из чего следует, что предзагрузчик не будет работать, как предполагалось.

Внешний предзагрузчик

Что же все-таки делать, если нам нужно:

  1. использовать attachMovie с достаточно "тяжелыми" (большими по размеру) клипами;
  2. создать предзагрузчик?

Можно сделать "внешний" предзагрузчик. Идея состоит в следующем. Основной ролик создается таким образом, как будто предзагрузчик использовать не предполагается (всем нужным символам устанавливается галочка " Export in first frame "). Кроме того, создается отдельный ролик, в котором:

  1. размещается трехкадровый цикл предзагрузчика ;
  2. основной ролик загружается с помощью loadMovie.

В основном ролике в первом же кадре проигрывание останавливается с помощью команды stop(), после того, как он полностью загрузится, его проигрывание запускает команда play() из ролика-загрузчика.

Объясним все на примере (рассматривается ролик-загрузчик, в основном ролике кроме команды stop() в первом кадре нет ничего специфического).

В первый кадр помещаем приблизительно такой код:

_root.createEmptyMovieClip("my_mc", 1);
// создаём пустой клип, в который будем загружать основной ролик;
my_mc.loadMovie("main.swf"); //загружаем основной ролик

Второй кадр оставляем пустым.

В третьем кадре пишем:

txt.text += my_mc.getBytesLoaded()/my_mc.getBytesTotal()+"\n";
// (или любой другой код, обновляющий проценты загрузки)
// если еще не все загрузили, ждем
if (my_mc.getBytesLoaded()/my_mc.getBytesTotal() < 1)
gotoAndPlay (2);

В четвертом кадре:

my_mc.play(); // запускаем проигрывание загруженного ролика
stop();       // останавливаем проигрывание:

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

Еще раз напомним, если в основном ролике используется runtime sharing, вы не сможете учесть размеры runtime-shared компонентов заранее.

Управление процессом выполнения

Хорошо, мы обеспечили заблаговременную загрузку основного ролика до начала его проигрывания (с помощью остановки его в первом кадре и контролирования процента загрузки).

А что делать, если мы все-таки используем runtime-shared модули в основном ролике? Вы уже поверили нам на слово, что вы не сможете отследить проценты их загрузки, но хотя бы заставить их все загрузиться до начала основной анимации мы можем? Да. Как именно - см. пункт "Контролируемая загрузка клипов" из раздела " runtime sharing " лекции, посвященной командной разработке.

Здесь же хочется упомянуть о хорошем приеме - скрытии (_visible = false) _root до полного окончания загрузки. Сделать этоможно в разных местах, можно из внешнего предзагрузчика, а можно - из шаблона (см. пункт "Управление процессом" раздела "Шаблоны для разработки" из лекции, посвященной командной разработке).

Для чего еще можно использовать предзагрузчики

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

Их задача более общая - управление процессом загрузки.

Рассмотрим еще одно важное применение предзагрузчиков - синхронизация асинхронных процессов - на примере загрузки ini-файлов.

Вы, наверное, обратили внимание, что пользоваться LoadVars не так уж удобно. Самое большое неудобство состоит в том, что нужно определять callback -обработчик, и только в нем становятся доступны нужные настройки. Иными словами, вы не можете использовать настройки в удобном для вас месте, потому что вы не знаете, загрузились они уже или нет. Поэтому вам приходится "чесать правой рукой левое ухо". Например, вместо того, чтобы в конструкторе компонента использовать уже готовый параметр "язык", вам приходится заводить центральный объект, который разошлет всем компонентам события "изменился язык, перерисуйтесь, пожалуйста", а это, согласитесь, намного более сложный механизм, и не вполне адекватный, ведь скорее всего вам никогда не понадобится по несколько раз менять язык флэш-ролика.

Вместо этого вы могли бы сделать предзагрузчик, который загрузит все необходимые ini-файлы и вообще сделает все подобные асинхронные вещи, после чего он загрузит основной ролик, который уже будет "на всем готовеньком" (общение основного ролика с предзагрузчиком, пожалуй, лучше организовать через какой-нибудь объект, размещенный в _global, чем использовать _level0 ).