Что есть вещатель класса
Частенько хочется, чтобы некая группа объектов на некое событие произвела некие действия.
Хм... неконкретно...
Частенько хочется, чтобы (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();
Забиваем Сайты В ТОП КУВАЛДОЙ - Уникальные возможности от SeoHammer
Каждая ссылка анализируется по трем пакетам оценки:
SEO, Трафик и SMM.
SeoHammer делает продвижение сайта прозрачным и простым занятием.
Ссылки, вечные ссылки, статьи, упоминания, пресс-релизы - используйте по максимуму потенциал SeoHammer для продвижения вашего сайта.
Что умеет делать SeoHammer
— Продвижение в один клик, интеллектуальный подбор запросов, покупка самых лучших ссылок с высокой степенью качества у лучших бирж ссылок.
— Регулярная проверка качества ссылок по более чем 100 показателям и ежедневный пересчет показателей качества проекта.
— Все известные форматы ссылок: арендные ссылки, вечные ссылки, публикации (упоминания, мнения, отзывы, статьи, пресс-релизы).
— SeoHammer покажет, где рост или падение, а также запросы, на которые нужно обратить внимание.
SeoHammer еще предоставляет технологию
Буст, она ускоряет продвижение в десятки раз,
а первые результаты появляются уже в течение первых 7 дней.
Зарегистрироваться и Начать продвижение
но, как мне кажется, это не лучший выход, поскольку хотя он и будет доступен из экземпляров этого класса,
все же хочется иметь доступ к вещателю и извне.
Можно создать объект в конструкторе класса, по типу 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.