Опубликован: 07.11.2006 | Уровень: специалист | Доступ: платный
Лекция 5:

Компоненты

Динамическое применение подсказки к фильму

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

Это сделать несложно, так как компоненты настраиваются на инициализацию так же, как и на добавление или перетаскивание на рабочем месте.

Единственным моментом, требующим внимания, является передача параметров фильму. Это можно сделать посредством передачи инициализационного объекта при вызове attachMovie, содержащего все параметры. Эти значения будут доступны подсказке при инициализации так же, как и значения из панели Components.

  1. Удалите подсказку с рабочего места и добавьте следующий код в главную временную диаграмму.
    obj = {
            ttEnabled:true, _targetInstanceName:"targ_mc",
             tooltipText: "whatever text you reckon",
            КmaxWidth:150, interval:50, x0ffset:6, y0ffset:-12
            }
        _root.attachMovie("tooltipMc","tt_mc",1,obj)

    Запустив код, вы увидите, что все работает правильно, но не очень удобно для пользователя, которому необходимо вводить множество данных с клавиатуры, причем если пользователь забудет ввести хотя бы один параметр, код работать не будет. Поэтому нам нужно как-то изолировать функцию init. Если какие-либо параметры не будут определены, мы будем устанавливать их на значения по умолчанию.

  2. Добавьте следующий выделенный код внутрь функции init компонента tooltip.
    tooltip.prototype.init = function() {
            this.bg_mc._visible = 0;
            this._visibie = 0;
            // with all of the following we check if the property
            // is defined and if not set a default value
            if (this.tooltiptext == undefined) {
                this.tooltiptext = "empty";
            }
            if (this.interval == undefined) {
                this.interval = 500;
            }
            if (this._parent[this._targetlnstanceName]) {
                this.setTarget(this._parent
                 [this._targetInstanceName]);
            }
            if (this.maxWidth == undefined) {
                this.maxWidth = 500;
            }
            if (this.xOffset == undefined) {
                this.xOffset = 12;
            }
            if (this.yOffset == undefined) {
                this.yOffset = -6;
            }
            if (this.ttEnabled == undefined) {
                this.ttEnabled = true;
            }
            this.setTarget(this._parent[this._targetInstanceName]);
            this.addProperty("tooltipText", this.getText, this.setText);
            this.addProperty("ttEnabled", 
              this.getEnabled, this.setEnabled);
            this.draw
        };

    Мы также вызываем функцию setTarget только в том случае, если у нас есть _targetInstanceName. В противном случае мы ждем, пока она не будет вызвана вручную.

  3. Теперь замените текст на главной временной диаграмме на следующий.
    _root.attachMovie "tooltipMc" , "tt_mc", 1);
        tt_mc.setTarget(targ_mc);
        tt_mc.tooltipText = "a piece of text";

    Сохраните фильм в файле finalTooltipbasicAttach.fla. Этот подход использует только значения по умолчанию, однако мы могли бы передавать инициализационный объект так же, как раньше передавали установки максимальной ширины, и т.д. Если значения на месте, они используются, в противном случае берутся значения по умолчанию.

Сохранение первоначальных функций кнопки

До сих пор весь наш код работал корректно и выполнял те действия, которые от него требовались. Несмотря на это, существует еще одна проблема.

  1. Удалите код на главном рабочем месте и перетащите новый инстанс подсказки на рабочее место над фильмом targ_mc. Теперь добавьте это код на главную временную диаграмму.
    targ_mc.onRollOver = function() {
            this._alpna = 50;
        };
        targ_mc.onRollOut = function() {
            this._alpha = 100;
        };

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

    Необходимо сохранять все функции, которые уже могут присутствовать и в фильме,и в подсказке, а именно в ее управляющих элементах onRollOver, onRollOut и onDragOut. Мы будем присваивать новые функции этим управляющим элементам, которые будут сначала вызывать старые функции, а затем выполнять действия, связанные с всплывающей подсказкой.

    Нам также нужно быть уверенными в том, что если пользователю нужно будет присвоить разные функции этим управляющим элементам, то все обновится еще раз для выполнения как новой функции, так и функции вызова подсказки. Для реализации этой возможности мы можем использовать еще один новый метод, доступный во Flash MX - метод Object.watch.

    Object.watch работает аналогично addProperty, позволяя следить за значением параметра или метода, а также вызывать указанную функцию каждый раз при изменении параметра. Это может использоваться для выяснения значения функции rollOver фильма и дальнейшего присвоения новой функции, что будет сначала вызывать эту новую функцию, а потом и саму подсказку.

  2. Добавьте следующий выделенный код в функцию setTarget. Имейте в виду, что мы удалили предыдущие определения управляющих элементов кнопки для конечного фильма и заменили их выражениями для "наблюдения".
    tooltip.prototype.setTarget = function(me) {
            this.targetMovie = me;
            this.targetMovie.toolTip = this;
            / / set watch points on the button actions of the target
            this.targetMovie.watch("onRollOver", this.addToRollOver);
            this.targetMovie.watch("onRollOut", this.addToRollOut);
            this.targetMovie.watch("onDragOut", this.addToDragOut);
            this.targetMovie.onRollOut = this.targetMovie.onRollOut;
            this.targetMovie.onRollOver = this.targetMovie.onRollOver;
            this.targetMovie.onDragOut = this.targetMovie.onDragOut;
        }

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

  3. Начнем с метода для хранения функции rollOver.
    tooltip.prototype.addToRollover = function(id, oldVal, newVal) {
            // store tne new rollover value in oldRollover
            this.tooltip.oldRollOver = newVal;
            // define the function that will be returned to the
            // target movieclip as its new rollover function
            return function    {
                // call the old Rollover function
                this.tooltip.oldRollover.call(this);
                / trigger the tooltip
                this.tooltip.wait = setlnterval
                  (this.tooltip, "displayTooltip" , 
                    this . tooltip, interval) ;
            };
        };

    Разберем каждую строку этого кода, начиная с определения функции.

    tooltip.prototype.addToRollover = function (id, oldVal, newVal) {

    Функции, вызываемой Object.watch, передаются три аргумента: id, oldVal и newVal. id ссылается на наблюдаемый параметр, oldVal представляет собой предыдущее значение, присвоенное параметру, а newVal - новое значение, присваиваемое параметру.

    this.tooltip.oldRollOver = newVal;

    Здесь мы сохраняем функцию, на которую установлен onRollOver или на которую пользователь попытался установить его, в переменной с именем oldRollOut внутри подсказки. Строго говоря, мы перехватываем это значение. Мы могли бы сохранить его в конечном фильме, но лучше по мере возможности избегать помещения в объект-цель различных элементов.

    Теперь возвращаем функцию, которая будет непосредственно настроена как onRollOver конечного фильма.

    return function () {
            this.tooltip.oldRollover.call(this);
            this.tooltip.wait = setlnterval(this.tooltip, "displayTooltip", 
                 this.tooltip.interval);

    Первая строка этого кода вызывает функцию oldRollover, а вторая устанавливает интервал до вызова displayTooltip, точно так же, как это делалось ранее. Вы могли заметить, что первая строка кода использует функцию call для вызова функции. Это по той причине, что функция oldRollover находится внутри подсказки. Но мы хотим, чтобы она действовала так, как если бы она находилась в конечном фильме. Наш исходный метод хранения oldRollOver внутри конечного фильма состоял в том, что мы имели бы только следующий код.

    this.oldRollover () ;

    Так как oldRollover находится внутри подсказки, а не в конечном фильме, мы не можем так поступить. Вместо этого мы используем function.call - еще одно новое дополнение к Flash MX. Оно позволяет осуществлять вызов функции, находящейся в каком-либо месте, как если бы она находилась где-то еще. Если вы обратите внимание на объявление прохода курсора (rollover), вы увидите, что местом, в котором выполняется код, является конечный фильм. Другими словами, this ссылается на конечный фильм.

    return function    {
        this.tooltip.oidRollover.call(this);
        this.tooltip.wait = setlnterval(this.tooltip, "displayTooltip", 
            this.tooltip.interval;
        };

    Когда мы используем function.call для вызова функции, то передаем аргумент (перед любыми другими аргументами, которые у нас могут быть), указывая место, в котором функция должна выполняться, в данном случае это this. По сути дела, это выражение означает "вызвать функцию oldRollover внутри фильма подсказки, однако выполнить ее так, будто она была бы в моей собственной временной диаграмме".

  4. Теперь мы можем создать функции для всех трех управляющих элементов rollOver. Две другие функции выполняют те же самые действия, вызывая clearTooltip вместо установки интервала для отображения подсказки.
    tooltip.prototype.addToRollover = function(id, oldVal, newVal) {
        this.tooltip.oldRollOver = newVal;
        return function () {
            this.tooltip.oldRollover.call(this);
            this.toolTip.wait = setlnterval(this.toolTip, "displayToolTip",
                 this.tooltip.interval);
         };
    };
    tooltip.prototype.addToRollOut - function(id, oldVal, newVal) {
        this.tooltip.oldRollOut = newVal;
        return function () {
            this.tooltip.oldRollOut.call(this);
            clearlnterval(this.toolTip.wait);
            this.toolTip.clearToolTip();
         };
    };
     tooltip.prototype.addToDragOut = function(id, oldVal, newVal) {
         this.tooltip.oldDragOut = newVal;
         return function () {
            this.tooltip.oldDragOut.call(this);
            clearlnterval(this.toolTip.wait);
            this.toolTip.clearToolTip();
         };
     };
  5. Сохраните фильм в файле finalTooltipbasicWatch.fla. При проверке фильма вы увидите, что проход указателя мыши теперь меняет яркость фильма и генерирует подсказку.

    Если мы посмотрим на исходный список возможностей подсказки, то станет видно, что нам осталось обеспечить лишь небольшую их часть. Нереализованными остались требования удаления подсказки и ее переключения с одного фильма на другой. Эти требования взаимосвязаны. На данный момент пользователь может просто удалить фильм с использованием tooltip.removeMovieClip(). Это будет действовать, однако когда подсказка будет удалена, будут удалены также все управляющие элементы onRollOver, и останется только ссылка на подсказку в конечном фильме.

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

    • Удалить ссылку на подсказку.
    • Удалить точки наблюдения, установленные на onRollOver, onRollOut и onDragOut.
    • Восстановить rollOver, rollOut и dragOut на их прежние значения.
    • Если не существует функций, определенных для этих управляющих элементов, то данные управляющие элементы будут удалены.
Игорь Хан
Игорь Хан

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

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

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

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

Тамара Ионова
Тамара Ионова
Россия, Нижний Новгород, НГПУ, 2009
Магомед Алисултанов
Магомед Алисултанов
Россия, Волгоград, лицей 2