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

Интерфейсы AсtionScript

Наблюдатели

Последнее, о чем я хотел бы рассказать в этой лекции, это совершенно новая возможность во Flash MX - наблюдатели. Здесь под этим термином не подразумевается человек, который наблюдает за чем-либо. Наблюдатель следит за переменной или параметром, и вызывает функцию при изменении переменной. Хотя это и не является поддержкой событий, данный процесс аналогичен ей в том, что происходит ожидание какого-либо события, и затем выполняется определенная функция.

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

Вернемся к нашему эксперименту с перетаскиванием и бросанием и проведем его заново с применением наблюдателя. Мы использовали onPress и onRelease/onReleaseOutside для начала и окончания перетаскивания фильма. В то же время мы устанавливали переменную с именем dragging на значение "истина" или "ложь". Мы будем отслеживать именно эту переменную. При ее изменении мы будем переключать управляющий элемент onEnterFrame фильма на другую функцию.

Для начала изучите синтаксис функции наблюдателя.

object.watch ("property", function);
  • object - это объект, фильм или временная диаграмма, где расположена переменная.
  • "property" - это параметр или переменная сама по себе. Обратите внимание, что это строковое значение, а не просто имя переменной.
  • function является обращением к функции, которая должна выполняться. watch будет передавать функции следующие параметры.
  • id - имя параметра.
  • oldval - значение параметра перед изменением.
  • newval - новое, текущее значение.

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


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

Вот наше выражение watch.

mc1_mc.watch ("dragging", dragHandler);

А вот как нужно начинать определение нашей функции dragHandler.

function dragHandler(id, oldval, newval){

  }

Сейчас нам не требуется использовать все эти параметры, но нам нужно определить нашу функцию с их использованием. В большинстве случаев вы будете работать только с параметром newval. Кроме всего прочего, новое значение параметра - это именно то, что нам интересно. Это как раз относится к нашему примеру. Мы знаем, что наша функция всегда вызывается на основе переменной dragging, поэтому нам уже известно, каким будет значение id. oldval также в данном случае не играет никакой роли.

Также необходимо учесть, что, как и в случае с функцией поддержки события, мы используем данную функцию для ссылки на данный объект. В функции dragHandler будет ссылка на mc1_mc.

Известо, что переменная dragging может иметь значение "истина" или "ложь", поэтому значение newval будет также иметь такой формат. Мы будем выполнять одно действие, если значением является "истина", и другое действие - в противном случае.

function dragHandler(id, oldval, newval) {
    if (newval) {
      this.onEnterFrame = drag;
    } else {
      this.onEnterFrame = move;
    }
    return newval;
  }

Обратите внимание на то, что мы просто написали if (newval):

Помните, что выражения if всегда превращают содержимое в значение "истина" или "ложь". Так как newval уже имеет формат истина/ложь, нам не нужно выполнять никаких дополнительных действий, например, сравнение, как в этом случае: if (newval = = true). Мы можем использовать данное выражение прямо в таком виде, в каком оно есть. Другим важным моментом, который нужно иметь в виду, является то, что в конце действий в функции наблюдения нужно добавлять строку return newval. Хотя это и не упоминается в документации, было выяснено, что если опустить эту строку, переменная, переданная функции наблюдения становится неопределенной! В нашем случае это означает, что переменная dragging, вместо того, чтобы иметь значение "истина" или "ложь", будет undefined. Возврат значения newval решает эту проблему.

Теперь вместо одной большой функции для onEnterFrame, проверяющей состояние переменной dragging много раз в секунду, мы разбили наши действия на две различные функции. Значение dragging проверяется только тогда, когда изменяется, поэтому здесь мы выиграли в производительности.

Теперь осталось только определить наши новые функции drag и move. Это просто две части нашей исходной функции onEnterFrame. Приведем конечный код нашего нового дополнения.

mc1_mc.onPress = function() {
    this.startDrag();
    this.dragqing = true;
  };
  mc1_mc.onRelease = mc1.onReleaseOutside = function() {
    this.stopDrag();
    this.dragging = false;
  };
  mc1_mc.watch("dragging", dragHandler);
  function dragHandler(id, oldval, newval) {
    if (newval) {
      this.onEnterFrame = drag;
    } else {
      this.onEnterFrame = move;
    }
    return newval;
  }
  function move() {
    this.xspeed *= .98;
    this.yspeed *= .98;
    this._x += this.xspeed;
    this._y += this.yspeed;
    if (this._x>550) {
      this._x = 0;
    } else if (this._x<0) {
      this._x = 550;
    }
    if (this._y>400) {
      this._y = 0;
  } else if (this._y<0) {
  this._y = 400;
    }
  }
  function drag() {
    this.xspeed = this._x-this.oldx;
    this.yspeed = this._y-this.oldy;
    this.oldx = this._x;
    this.oldy = this._y;
  }
Пример 6.3.

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

Сейчас, перед экспериментированием и реализацией ваших идей, вы должны знать, что у вас нет возможности устанавливать наблюдатели на большинство встроенных параметров фильмов, таких как _x и _y. Внутренние методы, используемые для доступа к этим параметрам, делают их несовместимыми с функцией watch. Это более детально описывается во Flash MX Reference по строке поиска watch.

И последнее. Аналогично сокращенному способу присвоения функций поддержки событий, мы можем использовать небольшой "ярлык" при написании функций watch. Мы просто определяем безымянную функцию и включаем ее прямо в выражение watch.

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

mc1_mc.watch("dragging",
  function (id, oldval, newval){
    if (newval) {
      this.onEnterFrame=drag;
    } else {
      this.onEnterFrame=move;
    }
  })

А здесь все написано так, как вы обычно будете видеть.

mc1_mc.watch ("dragging", function (id, oldval, newval))	{

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

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

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

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

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

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