Опубликован: 07.11.2006 | Доступ: свободный | Студентов: 3400 / 338 | Оценка: 3.94 / 3.71 | Длительность: 37:11:00
Лекция 6:

Движемся дальше

Загрузчик XML

Интерфейс, создаваемый нами, будет составной частью сайта, поэтому добавим загрузчик данных XML. Мы создадим простой текстовый индикатор состояния, который будет отображать процент загрузки данных, а также выводить сообщение в случае неудавшейся загрузки XML. Нам нужно добавить код для метода tweenTo, установить метод setBrightness из предыдущей лекции и созданный нами объект Stage.

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

#include "tweento.as"
    #include "brightness.as"
    #include "stage.as"

Хорошей практикой считается использование таких фрагментов кода при работе с объектами. Когда Flash доходит до выражения include при компиляции SWF, то добавляет содержимое указанного в include файла. Последняя строка файла AS обязательно должна заканчиваться точкой с запятой! Одной из новых возможностей во Flash MX является глобальный путь include. Обычно при использовании выражения include нужно убедиться в том, что файлы AS находятся в той же директории, что и включающий их файл Flash. Глобальный путь позволяет сохранять любые файлы AS и предоставлять к ним доступ всем фильмам. На компьютере этот путь выглядит так: C:\Program Files\Macromedia\Flash MX\Configuration\ Include - папку include вы создаете сами. Когда Flash дойдет до выражения include, сначала будет осуществлен поиск в локальной директории, и если файл AS не будет найден в этой папке, то его поиск будет продолжен в глобальной папке include.

Здесь нужно включить три файла, для каждого из которых ниже указан ActionScript. Если вы не хотите вводить их заново или копировать из предыдущих файлов, возьмите их из исходных файлов для этой лекции.

Приведем содержимое каждого из трех файлов.

Подключение внешнего кода: tweenTo.as

MovieClip.prototype.tweenTo = function(targetsObj, speed, callbackObj,callbackFunc) {
        var noo
        if (this.tweenControl) {
            noo = this.tweenControl;
        } else {
            noo = this.createEmptyMovieClip("tweenControl",this.depth++);
        }
        noo.targetsObj = targetsObj;
        noo.speed = speed;
        noo.callBackObj = callBackObj;
        noo.callBackFunc = callBackFunc;
        noo.onEnterFrame = function() {
            var count;
            // as its an object we can't check length,
            for (var prop in this.targetsObj) {
                this._parent[prop] += (this.targetsObj [prop]-
                Кthis._parent [prop] ) /this. speed;
                if (Math.abs(this.targetsObj [prop]-this._parent [prop] ) <0.9) {
                    this._parent[prop] = this.targetsObj [prop];
                    delete this.targetsObj [prop];
                }
                count++;
            }
            if (!count) {
                this.callBackObj [this.callBackFunc](this._parent);
                this.removeMovieClip();
            }
        };
    };
Пример 5.8.

Подключение внешнего кода: brightness.as

Color.prototype.setBrightness = function(bright) {
        var aNum = 100-Math.abs(bright);
        var bNum = bright<0 ? 0 : Math.ceil(255*bright/100);
        this.setTransform({ra:aNum, ga:aNum, ba:aNum, aa:100,
        Кrb:bNum, bb:bNum, ab:0});
    };

Подключение внешнего кода: stage.as

fscommand("allowscale", "false");
    Stage.scaleMode="showAll";
    Stage.originalWidth = Stage.Width;
    Stage.originalHeight = Stage.Height;
    Stage.scaleMode="noScale"
    Stage.onResize = function() {
        this.left = this.getLeft();
        this.top = this.getTop();
        this.right = this.getRight();
        this.bottom = this.getBottom();
    };
    Stage.getLeft = function() {
        return -1*(Stage.width-this.originalWidth)/2;
    };
    Stage. getTop = function() {
        return -1*(Stage.height-this.originalHeight)/2;
    };
    Stage. getRight = function() {
        return this.left+this.width;
    };
    Stage. getBottom = function() {
        return this.top+this.height;
    };
    Stage.addListener(Stage);
    // ensure onResize is called at start
    Stage.onResize();
Пример 5.9.

Создание загрузчика XML

Теперь внешние файлы ActionScript включены, и мы займемся кодом для фильма.

  1. Добавим новый слой scripts. Прежде всего мы создадим функцию для текстового отображения состояния фильма. Мы начнем с объекта текста TextFormat, который добавим под нашими выражениями include.
    statusTf = new TextFormat("Arial", 40, 0x4375A6);
        statusTf.align = "center";
        statusTf.leading = -5;
            Текущий код будет выглядеть так.
        #include "tweento.as"
        #include "brightness.as"
        #include "stage.as"
    
        statusTf = new TextFormat("Arial", 40, 0x4375A6);
        statusTf.align = "center";
        statusTf.leading = -5;
  2. На другом слое добавим динамическое текстовое поле сразу за верхней частью рабочего места. С помощью ActionScript укажем его местоположение. Выделим текстовое поле и добавим все символы Arial (или любого другого шрифта), нажав кнопку Character: в Property inspector. В диалоговом окне Character Options выберем опцию All Characters и нажмем кнопку Done.

  3. В Property inspector назовем текстовое поле embedder и введем следующий выделенный код, чтобы сделать поле невидимым.
    embedder._visible = 0;
        statusTf = new TextFormat("Arial", 40, 0x4375A6);
        statusTf.align = "center";
        statusTf.leading = -5;
  4. Мы также добавим переменную filename (выделено жирным шрифтом) для указания файла XML, нужного для загрузки. Здесь нам не понадобится использовать переменную, однако это упростит изменение имени файла при необходимости.
    _root.filename = "pictures.xml";
        embedder._visible = 0;
        statusTf = new TextFormat("Arial", 40, 0x4375A6);
        statusTf.align = "center";
        statusTf.leading = -5;
  5. Теперь мы добавим функцию createStatusMovie для создания текстового поля, установим формат текста и затем установим текст на значение, которое передается функции.
    function createStatusMovie(tex) {
            _root.createEmptyMovieClip("statusClip", 1);
            statusClip.createTextField
               ("statusText", 1, 0, 0, 550, 100);
          //	set properties of textfield
            statusClip.statusText.embedFonts = true;
            statusClip.statusText.selectable = false;
            statusClip.statusText.setNewTextFormat(statusTf);
            statusClip.statusText.text = tex;
            statusClip._x = 0;
            statusClip._y = (Stage.originalHeight- 
              statusClip.statusText.textHeight)/2-50;
        }

    Мы используем объект Stage для расположения текстового поля довольно далеко от центра по вертикали, а для горизонтального центрирования используем настройку выравнивания текстового поля. Функция createStatus будет вызываться при первом импорте XML. Мы можем использовать такую же функцию для создания загрузчика отдельных изображений.

  6. Для создания предзагрузчика XML мы используем методы getBytesLoaded и getBytesTotal объекта XML. Если поделить getBytesLoaded на getBytesTotal и затем умножить на 100, получим результат в процентах, представляющий собой загруженный XML. Функция updateXmlStatus будет вычислять процент и отображать результат в текстовом поле. Используем setInterval для регулярного вызова данной функции. Некоторая часть следующего кода функции importXml будет аналогична коду предыдущего раздела, где мы сначала импортировали наши данные XML во Flash. Новый код выделен жирным шрифтом.
    function importXml() {
            pictureObjects = [];
            myXml = new XML();
            myXml. ignoreWhite = true;
            // method to update display
            myXml.updateXmlStatus = function() {
                var percent = Math.round(this.getBytesLoaded()/
                Кthis.getBytesTotal()*100);
                if (percent<=0) {
                    percent = "0";
                }
                _root.statusClip.statusText.text = "PICTURE DATA LOADING
                К\n" percent+"%";
            };
            // use setlnterval to call updateXmlStatus every 20
            //milliseconds
            myXml.updater = setlnterval(myXml, "updateXmlStatus", 20);
            myXml.onLoad = parseMe;
            myXml.load(_root.filename);
            _root.createStatusMovie("PICTURE DATA LOADING");
        }

    Рассмотрим функцию updateXmlStatus.

    myXml.updateXmlStatus = function() {
            var percent = Math.round
              (this.getBytesLoaded()/this.getBytesTotal()*100);
            if (percent<=0) {
                percent = "0";
            }
            _root.statusClip.statusText.text = 
               "PICTURE DATA LOADING \n"+percent+"%";
        };

    Прежде всего, мы вычисляем процентное значение и округляем его, чтобы избавиться от десятичной части. Когда вызов загрузки XML происходит в первый раз (перед тем, как Flash свяжется с сервером или примет любую информацию о файле), getBytesTotal возвращает значение undefined. Тогда процентное значение будет равно нулю, деленному на undefined, что, естественно, не даст никакого результата, и будет возвращено значение NaN (не число).

    Чтобы предотвратить отображение этого значения в виде процентов, мы выполняем проверку на percent. Так как NaN воспринимается Flash как значение, меньшее нуля, мы проверяем, является ли процентное значение меньшим, чем ноль и, если это так, просто устанавливаем percent на значение ноль. В последней строке мы обновляем отображаемый текст, добавляя новую строку после PICTURE DATA LOADING.

  7. Теперь рассмотрим, как отображать сообщение, если что-то происходит неправильно. Это можно реализовать, значительно изменив функцию parseMe. Когда функция присваивается управляющему элементу onLoad объекта XML, ей передается один параметр при происхождении события onLoad. Если XML загружен успешно, передается значение "истина", в противном случае - "ложь". Итак, мы изменяем нашу предыдущую функцию parseMe для проверки этого значения и выполнения действий с его использованием. Новый код выделен жирным шрифтом.
    function parseMe(success) {
            // if the xml has loaded successfully
            if (success) {
                var pictures = this.firstChild.childNodes;
                for (var i = 0; i<pictures.length; i++) {
                    var obj = {};
                    for (var j in pictures[i] .attributes) {
                        obj [j] = pictures [i] .attributes [j];
                    }
                    pictureObjects.push(obj);
                }
                // stop calling the display update function
                clearInterval(this.updater);
                _root.pictureDataComplete();
                this.updateXmlStatus();
                //statusClip.removeMovieClip()
            } else {
            _root.statusClip.statusText.text = "FAILED TO LOAD DATA";
            clearInterval(this.updater);
            }
        }

    Если загрузка не удалась, мы изменяем statusText для чтения FAILED TO LOAD DATA. Независимо от того, была загрузка успешной или нет, вызывается интервал updateXmlStatus. При непосредственном использовании кода мы будем удалять клип состояния сразу по завершении загрузки, однако сейчас мы оставим его, чтобы убедиться в правильности функционирования вызова статуса, т.к. в противном случае сообщение будет исчезать практически мгновенно.

  8. Добавим функцию pictureDataComplete, которая будет вызываться после загрузки XML, и функцию init для начала загрузки XML. Приведем окончательный код. Жирным шрифтом выделены функции pictureDataComplete и init.
    #include "tweento.as"
        #include "brightness.as"
        #include "stage.as"
        _root.filename = "pictures.xml";
        embedder._visible = 0;
        statusTf = new TextFormat("Arial", 40, 0x4375A6);
        statusTf.align = "center";
        statusTf.leading = -5;
        function createStatusMovie(tex) {
            _root.createEmptyMovieClip("statusClip", 1);
            statusClip.createTextField("statusText", 1, 0, 0, 550, 100);
            statusClip.statusText.embedFonts = true;
            statusClip.statusText.selectable = false;
            statusClip.statusText.setNewTextFormat(statusTf);
            statusClip.statusText.text = tex;
            statusClip._x = 0;
            statusClip._y = (Stage.originalHeight- statusClip.statusText.textHeight)/2-50;
        }
        function importXml() {
            pictureObjects - [];
            myXml = new XML();
            myXml.ignoreWhite = true;
            myXml.updateXmlStatus = functionO {
                var percent = Math.round(this.getBytesLoaded() / this.getBytesTotal()*100);
                if (percent<=0) {
                    percent = "0";
                }
                _root.statusClip.statusText.text = "PICTURE DATA LOADING \n"+percent+"%";
            };
            myXml.updater = setInterval(myXml, "updateXmlStatus", 20);
            myXml.onLoad = parseMe;
            myXml.load(_root.filename);
            _root.createStatusMovie("PICTURE DATA LOADING");
        }
        function parseMe(success) {
            if (success) {
                var pictures = this.firstChild.childNodes;
                for (var i = 0; i<pictures.length; i++) {
                    var obj = {};
                    for (var j in pictures[i].attributes) {
                        obj [j] = pictures [i] .attributes [j];
                    }
                    pictureObjects.push(obj);
                }
                clearlnterval(this.updater);
                _root.pictureDataComplete();
                this.updateXmlStatus();
                //statusClip.removeMovieClip()
            } else {
                _root.statusClip.statusText.text = "FAILED TO LOAD DATA";
                clearlnterval(this.updater);
            }
        }
        function pictureDataComplete() {
            trace("picture data loaded");
        }
        function init() {
            importXml () ;
        }
        init();
    Пример 5.10.

    Если вы запустите файл без его сохранения, вы получите сообщение FAILED TO LOAD DATA, т.к. FLA и pictures.xml не сохранены в той же папке. Сохраните фильм в файле xmlLoader.fla и запустите его снова. На этот раз, как мы и планировали, будет выведено сообщение PICTURE DATA LOADING 100%:


Игорь Хан
Игорь Хан

у меня аналогичная ситуация. Однако, если взять пример из приложения (ball_motion_04_click for trial.fla) то след остается. при этом заметил, что в моем проекте в поле "One item in library" виден кружок, в то время как в приложенном примере такого кружка нет.

Вопрос знатокам, что не так?

Александр Коргапольцев
Александр Коргапольцев

объект созданый мной упорно не желает оставлять след(единственное что добился, так это то что шарик резво гоняется за курсором) функция duplicateMovieClip остаётся не активной, т.е. следа от объекта не остаётся, но если я тоже самый код вбиваю в учебный файл всё работает, не могу понять где я ошибаюсь и почему в документе созданном заново, не работает код начиная от функции duplicateMovieClip?