Оцените мой сайт
1. Отлично
2. Хорошо
3. Неплохо
4. Плохо
5. Ужасно
Всего ответов: 37
Главная » Статьи » Статьи о флеш

“Вещатель класса”

Что есть вещатель класса 

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

Частенько хочется, чтобы (a) все шарики на сцене (б) при клике (в) перекрасились. 

Или что-то в этом роде. 

Короче хочется, чтобы (a) некая группа объектов (б) на некое событие (в) произвела некие действия. 
Опять в ту же степь. Но теперь надеюсь понятней, если сопоставить.  

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

for (var i=0; i<10; i++) { this["mc”+i].removeMovieClip() }

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

Подготовительные работы

Создадим в либе мувик, нарисуем квадратик 10×10, обзовем его ball_mc и проставим тот же Linkage.  

После применения волшебной комбинации Esc+s+c 
 заменим трёху баксов на всенародно любимый 
Ball и удалим инитклип. 
В итоге должны получить следующее:

this.setBallClass = function() { delete this.setBallClass; var BallClass = _global.Ball = function () { this.init(); }; Object.registerClass(‘ball_mc’, BallClass); ASSetPropFlags(_global, ‘Ball’, 7, 1); var tmp = BallClass.prototype=new MovieClip(); tmp.init = function() { }; }; this.setBallClass();


Имеем в итоге класс. 

Дальше стоит поразмышлять, кого мы назначим вещателем. 

В принципе можно создать приватный объект и заставить его быть вещателем (добавленное выделено):

this.setBallClass = function() { delete this.setBallClass; var BallClass = _global.Ball=function () { this.init(); }; var class_broadcaster = {}; AsBroadcaster.initialize(class_broadcaster); Object.registerClass(‘Ball_mc’, BallClass); ASSetPropFlags(_global, ‘Ball’, 7, 1); var tmp = BallClass.prototype=new MovieClip(); tmp.init = function() { }; }; this.setBallClass();


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



Можно создать объект в конструкторе класса, по типу static в AS2:

this.setBallClass = function() { delete this.setBallClass; var BallClass = _global.Ball=function () { this.init(); }; BallClass.class_broadcaster = {}; AsBroadcaster.initialize(BallClass.class_broadcaster); Object.registerClass(‘Ball_mc’, BallClass); ASSetPropFlags(_global, ‘Ball’, 7, 1); var tmp = BallClass.prototype=new MovieClip(); tmp.init = function() { }; }; this.setBallClass();


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

Как это ни странно, это конструктор класса! 
Смотрим:

this.setBallClass = function() { delete this.setBallClass; var BallClass = _global.Ball=function () { this.init(); }; AsBroadcaster.initialize(BallClass); Object.registerClass(‘Ball_mc’, BallClass); ASSetPropFlags(_global, ‘Ball’, 7, 1); var tmp = BallClass.prototype=new MovieClip(); tmp.init = function() { }; }; this.setBallClass();

С моей точки зрения использование конструктора класса в качестве вещателя идеально подходит для наших целей.

Но заранее скажу: за всю практику использования конструктора класса в качестве вещателя класса я не нарвался на неприятности или неудобства. 

Ок. Это не всё, что придется сделать. 
Требуется сделать удобный вызов вещания событий из любого экземпляра класса и из любого места программы. 
Требуется также сделать экземпляры класса слушателями и тестануть всё это добро.
Заодно откомментирую:

// задаем метод - инициализатор класса: this.setBallClass = function() { // если мы не собираемся реинициализировать этот класс, // то и метод - инициализатор класса не нужен, удаляем при первом вызове: delete this.setBallClass; // далее задаем конструктор класса, при этом // задаем две ссылки на этот констуктор: локальную и глобальную var BallClass = _global.Ball=function () { // я не рекомендую писать необходимый код непосредственно в конструкторе. // советую всегда для этого использовать отдельный метод init // и вызывать его в конструкторе класса this.init(); }; // это то, ради чего мы здесь собрались, // инициализируем конструктор класса в качестве вещателя: AsBroadcaster.initialize(BallClass); // Создадим специальный метод, который будет вызывать вещание события: BallClass.onMessage = function() { // вещаем, оптом отдавая все аргументы: this.broadcastMessage.apply(this, arguments); // и на закономерный вопрос: // - а нахрена оно нам надо, если в этом методе ничего не происходит, //кроме переадресации вызова? // отвечу: // если потребуется вызвать вещание сразу на несколько классов, // то могут потребоваться проверки типа: // а нужно ли вещать на этот класс? вот в этом методе, //перед вызовом вещания и поставим такую проверку }; // регистрируем мувик в классе Object.registerClass(‘ball_mc’, BallClass); // предохраняем от неприятностей ссылку на конструктор класса в _global ASSetPropFlags(_global, ‘Ball’, 7, 1); // задаем наследование от MovieClip и делаем локальную ссылку на прототип класса var tmp = BallClass.prototype=new MovieClip(); // ЗАДАЕМ МЕТОДЫ КЛАССА // init, вызываемый в конструкторе класса tmp.init = function() { // немедленно добавляет экземпляр класса в список слушателей вещателя класса BallClass.addListener(this); }; // задаем вызов вещания из экземпляра класса: tmp.onMessage = function() { // обращаясь к вещателю класса с использованием локальной переменной, // также оптом отдаем все аргументы BallClass.onMessage.apply(BallClass, arguments); // это, кстати, не единственный способ. // можно использовать для этих же целей this.constructor }; // добавляем реакцию на клик tmp.onRelease = function() { // вызываем событие killAll с дополнительным аргументом this this.onMessage("killAll”, this); }; // задаем обработчик события killAll tmp.killAll = function(mc) { // если событие пришло не от самого себя if (mc != this) { // то самоудаляемся this.removeMovieClip(); } }; // если кто-то нас снес, tmp.onUnload = function() { // то нужно и удалить себя из списка слушателей: BallClass.removeListener(this); }; }; // инициализируем класс this.setBallClass(); ////////////////////////////// TEST //////////////////// // каждый кадр this.onEnterFrame = function() { // случайно, один из 20 раз if (!(random(20))) { // увеличиваем счетчик this.i = this.i+1 || 0; // аттачим квадратик на сцену в случайную позицию this.attachMovie("ball_mc”, "ball"+this.i, this.i, {_x:random(400), _y:random(300)}); } };

При тестировании этого кода может обнаружиться странная закономерность: 
если кликнуть по любому появившемуся кавдратику, то удалятся все остальные, кроме него. 
Как это ни странно целью представленного кода было именно это.

Теперь сравните этот простой и наглядный код с тем, который был представлен в самом начале. 
Не правда ли, всё стало горазод проще и понятнее?



Доступ извне 

Как говорилось выше, иногда требуется отдать команду извне на выполнение метода в каждом из существующих экземпляров класса. 
Это очень просто:

on (release) { Ball.onMessage("killAll") }

Вкусности 

Поскольку конструктор класса инициализирован в качестве вещателя, у него имеется, массивчик, именуемый _listeners. 
А у массивчика всегда имеется длина. Догадались, к чему я клоню? Если создать текстовое поле в руте, 
задать ему имя экземпляра t_txt, а затем в классе Ball после добавления и удаления слушателя добавить строку:

_root.t_txt.variable = "_global.Ball._listeners.length"

то получим неплохой счетчик, отражающий реальное количество присутствующих экземпляров класса.

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

BallClass.addProperty("instances", function () { return this._listeners.length; }, null);

Вот пожалуй, на этом пока всё.

Автор: Ivan Dembicki aka Iv.

Категория: Статьи о флеш | Добавил: Falanga (13.12.2009)
Просмотров: 435 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Понедельник
13.05.2024
07:44


Логин:
Пароль:
Текст/Код

Онлайн всего: 1
Гостей: 1
Пользователей: 0
200


Хостинг от uCoz