On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru






 

Создание блоков кнопок с зависимой фиксацией

Прототипы для создания блоков кнопок с зависимой фиксацией


В своем уроке "Дублирование клипов при помощи прототипа" я рассказал о применении
прототипа для дублирования мувиков, и, в частности - мувиков с кнопками и заголовками.

Теперь попробуем применить приобретенные знания для создания блока кнопок с
зависимой фиксацией, т.е такого набора кнопок, в котором нажатие любой из них
привело бы к автоматическому отключению ранее нажатой кнопки. Ну, как переключатель
диапазонов в приемнике. Их так и называют - радиокнопки (RadioButtons).
В этом уроке, как и прежде, я не стану рассказывать о том, как рисуется кнопка,
а буду исходить из предположения, что все вещи, связанные с такими базовыми операциями,
вам давно известны. Я также предполагаю, что вы достаточно прочно владеете AS,
в противном случае многое вам будет просто не вполне понятно, объяснять же азы AS -
это тема совсем другого урока...

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

Кнопка.

Нарисуем простую кнопку (можно - сложную, если не лень), в которой имеется поле
для заголовка, имеющее, естественно, какое-то имя. Например, caption. Поместим
эту кнопку в новый мувик и назовем его movbtn,

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

Теперь можно приступить к решению самой задачи.

Блок кнопок

Создадим еще один пустой мувик, в который поместим нашу кнопочку, вернее, мувик
с кнопочкой. В дальнейшем, когда я буду говорить о кнопке, я всегда буду иметь
в виду именно мувик, в который помещена кнопка.
Итак, мы поместили мувик с кнопкой в другой мувик. Этот мувик будет ни чем иным,
как будущим блоком кнопок. Чтобы из одиночной кнопки сотворить блок, можно,
конечно, натыкать в него несколько экземпляров кнопки. Но это - не наш метод,
мы будем кнопку дублировать. Саму процедуру дублирования отложим на потом,
а пока напишем пару полезных прототипов для управления самой кнопкой. Сам мувик
с вложенным в него мувиком с кнопкой назовем blockbtn, а мувику с кнопкой
внутри этого blockbtn присвоим имя movbtn0. Наличие нуля в конце имени очень
важно для последующей обработки события в блоке при помощи одной общей процедуры.

Прототип для установки цвета

Во-первых, почему прототип? Дело в том, что нам, возможно, придется дублировать
любые кнопки, процедуры должны быть не одноразовыми, а применимыми к чему
угодно и не зависеть от внутренней структуры кнопок. К тому же, нам потребуются
некоторые параметры, которые мы будем назначать кнопкам дополнительно, они должны
быть одинаковыми для всех кнопок и не зависеть от их количества. Если я не убедил
вас - просто поверьте на слово, без прототипа эта задача, конечно, решаема,
но - сколько грязи будет! Итак, используем прототипы.
Прототип установки цвета нам понадобится для того, чтобы управлять цветом нашего
встроенного в кнопку (в мувик с кнопкой!) флажка.

movieClip.prototype.setColor=function(movieName,RGB){
myColor = new Color(this[moviename]);
myColor.setRGB(RGB);
}

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

Прототип нажатия кнопки

movieClip.prototype.press=function(){
this.flag*=-1;
this.flag == 1? this.setColor (this._flagname,this.colon) : this.setColor (this._flagname,this.coloff);
}

Тут - тоже все просто. Если внутри мувика есть кнопка, то в зависимости от ее
прежнего состояния она по нажатии будет или включаться, или - выключаться, меняя
цвет своего флажка и значение внутреннего флага.
Заметьте, что внутри прототипа присутствуют некие параметры - flag, colon и coloff,
Мы их пока что нигде не определили и определять не будем, т.к. в противном случае
вся процедура создания блока и управления им будет сильно зависеть от внутреннего
содержимого кнопки, чего никак бы не хотелось. Поэтому определим эти параметры
непосредственно в прототипе дублирования кнопки, тем самым автоматически добавляя
эти параметры в любые кнопки, которые могут быть использованы для создания
кнопочного блока.
Запишем эти два прототипа в файл с именем bb.as и пока о них забудем.
Вернемся к нашему мувику с кнопкой (мы назвали его, как вы помните, movbtn).
Откроем его для редактирования и посадим на вложенную в него кнопку обработчик события:

on (release) {
this.press();
}

Теперь мы получили не просто кнопку, а кнопку с фиксацией. Осталось продублировать
эту кнопку внутри блока (мувика blockbtn). Напишем прототип дублирования.

Прототип для создания блока кнопок

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

Начнем с заголовка.

movieClip.prototype.makeButtonBlock=function
(n, instStart, x0, y0, dx, dy, captionName, captions, nOn, flagName, flagColor1, flagColor2){

Уточню сразу. Все параметры, перечисленные в заголовке - формальные. Они никак
не связаны с реальными, присутствующими в кнопке или в программе.
В заголовке прототипа:
n - количество кнопок в будущем блоке;
instStart - номер инстанса, с которого будет происходить дублирование кнопок.
Вы ведь можете поместить в сцену несколько БКЗФ, независимых один от другого,
поэтому количество дубликатов нужно учитывать!
x0,y0,dx,dy - начальные координаты и смещения по x и y для кнопок;
captionName - имя заголовка внутри кнопки;
captions - имя массива, в который вы запишете свои заголовки кнопок;
nOn - номер кнопки, которая должна быть включена при создании блока
(если ничего включать не нужно - посдставим потом -1;
flagName - имя мувика с флажком (помните? Мы его назвали flagball);
flagColor1, flagColor2 - звета включенного и выключенного флажков.

Теперь, определившись с параметрами, которые нам понадобятся для дублирования
кнопок, перейдем к содержимому прототипа.

Нам необходимо, чтобы каждый экземпляр кнопки содержал в себе максимум
информации о том, какие именно параметры в нем могут изменяться, какие принимать
значения, а также - некоторые параметры, общие для всего блока. Помните, те самые
flag, colon и coloff? Если мы не сделаем этого, нам придется в дальнейшем,
при управлении кнопками, передавать эти значения через заголовки будущих
процедур, а это не есть хорошо, а пожалуй - и плохо. Мы попадем в зависимость
от нашей конфигурации и вместе с изменениями в кнопках, придется менять и их
процедуры. Далее вы убедитесь в этом, пока же запишем:
this.colon=flagcolor1;
this.coloff=flagcolor2;
this._flagname=flagname;
this.numBtns=n;
Таким образом, мы придаем нашему "образцу для подражания" некие новые свойства -
храним в нем информацию о цветах, об имени внутреннего цветового флажка, о
количестве кнопок в блоке.
var name=this._name;
myColor = new Color(_parent[name].flagball);
if(nOn==0){
myColor.setRGB(flagcolor1);
this.flag=1;
}else {
myColor.setRGB(flagcolor2);
this.flag=-1;
}
Здесь мы проверили, должен ли образец быть включен при прорисовке блока, и,
соответственно, раскрасили его. Кроме того, мы создали новый внутренний параметр
- flag , который нам понадобится в дальнейшем для переключения, да и для
выполнения разумных действий по нажатию кнопки - тоже.
if (name.charAt (name.length - 1) == "0") {name = name.substr (0, name. length-1)}
var basename=name;
this.basename=name;
myname=name;
this.fullname=_parent._name+"."+basename;
Как я уже писал в прошлом уроке, желательно имя первой кнопки заканчивать нулем -
для единообразия. Тут я сформировал базовое имя, заодно сохранив его вместе с
именем будущего блока в самой кнопочке. Эти вещи не совсем очевидны, но вы
сможете постепенно разобраться во всем этом сами. А можете и не разбираться,
а просто использовать готовое решение. Работать-то будет независимо от вашего понимания.

this._x=x0;
this._y=y0;

this[captionname]=captions[0];
var yt=y0;
var xt=x0;
Наконец, мы определились с положением образца и с его заголовком. Теперь можно
заняться дублированием, при этом не забывая записать в каждый вновь созданный
экземпляр те же параметры, что были записаны для образца.

for (i=1;i<n;i++){
name=basename+i;
yt+=dy;
xt+=dx;
this.duplicateMovieClip(name,i+instStart);
_parent[name].colon = flagcolor1;
_parent[name].coloff = flagcolor2;
_parent[name]._flagname=flagname;
_parent[name]._y=yt;
_parent[name]._x=xt;
_parent[name][captionname]=captions[i];
_parent[name].numBtns=n;
_parent[name].basename=myname;
_parent[name].fullname=_parent._name+"."+basename;
Беда с этими "парентами", а что делать... мы ведь будем работать в дальнейшем с
блоком в целом, а не с отдельными кнопками... придется терпеть.
myColor = new Color(_parent[name].flagball);
myColor.setRGB(flagcolor2);
if(nOn==i){
myColor.setRGB(flagcolor1);
_parent[name].flag=1;
}else {
myColor.setRGB(flagcolor2);
_parent[name].flag=-1;
}

}
}
Ну, вот, мы закончили первый прототип. Еще раз посмотрим, как он будет
выглядеть в целом.

movieClip.prototype.makeButtonBlock = function
(n, instStart, x0, y0, dx, dy, captionName, captions, nOn, flagname, flagcolor1, flagcolor2){
this.colon=flagcolor1;
this.coloff=flagcolor2;
this._flagname=flagname;
this.numBtns=n;
var name=this._name;
myColor = new Color(_parent[name].flagball);
if(nOn==0){
myColor.setRGB(flagcolor1);
this.flag=1;
}else {
myColor.setRGB(flagcolor2);
this.flag=-1;
}

if (name.charAt (name.length - 1) == "0") {name = name.substr(0, name.length-1)}
this.basename=name;
myname=name;
this.fullname=_parent._name+"."+basename;
this._x=x0;
this._y=y0;
this[captionname]=captions[0];
var yt=y0;
var xt=x0;
for (i=1;i<n;i++){
name=basename+i;
yt+=dy;
xt+=dx;
this.duplicateMovieClip(name,i+instStart);
_parent[name].colon=flagcolor1;_parent[name].coloff=flagcolor2;
_parent[name]._flagname=flagname;
_parent[name]._y=yt;
_parent[name]._x=xt;
_parent[name][captionname]=captions[i];
_parent[name].numBtns=n;
_parent[name].basename=myname;
_parent[name].fullname=_parent._name+"."+basename;
myColor = new Color(_parent[name].flagball);
myColor.setRGB(flagcolor2);
if(nOn==i){
myColor.setRGB(flagcolor1);
_parent[name].flag=1;
}else {
myColor.setRGB(flagcolor2);
_parent[name].flag=-1;
}
}
}

Если по-честному, то я и сам долго бодался с этим прототипом, прежде, чем получил
желаемый результат. Допишем его в файл с именем bb.as и опять забудем о нем.
Поехали дальше!

Создание блока кнопок

Откроем наш мувик blockbtn и в его первом (и последнем) кадре напишем:

color1=0x3399cc;
color2=0xcc9933;

capt=new array ("Кот", "Пес", "Корова", "Лошадь", "Коза");
movbtn0.makeButtonBlock(5,0,0,0,0,20,"caption",capt,0,"flagball",color1,color2);

Что же мы сделали? А мы определили внутри кнопочного блока цвета наших флажков
(вкл. и выкл.), заголовки кнопок и продублировали кнопку movbtn0, создав кнопочный блок.
Давайте посмотрим, как это работает.

Поместим наш blockbtn в сцену и напишем в ней:

#include "bb.as"
stop();

Запустим. О, чудо, у нас получился кнопочный блок! Но он работает не совсем так,
как хотелось бы. Кнопки работают как независимые, каждая из них включается и
выключается автономно. А мы хотели - с фиксацией!
Что же, напишем последнюю процедуру. Теперь уже мы не будем писать прототип,
т.к. прототип пишется для отдельного (хотя, и любого) мувика, а нам нужна
обработка всех кнопок блока сразу.

function turnButtonsOff(n,fullname){
for(i=0;i<n;i++){
name=fullname+i;
if (eval(name).flag==1){
eval(name).flag*=-1;
eval(name).flag==1? Eval (name). setColor(eval(name)._flagname,eval (name).colon) :
eval(name).setColor (eval(name)._flagname,eval (name).coloff);

}
}
}

Заметьте, что внутри этой функции мы указываем количество кнопок в блоке и имя
fullname, которые были нами определены как внутренние параметры кнопок при их
дублировании и - flag, colon и coloff - были опять-таки определены при дублировании кнопок.
Эту процедуру поместим в первый кадр сцены , который теперь будет выглядеть так:

#include "bb.as"


function turnButtonsOff(n,fullname){
for(i=0;i<n;i++){
name=fullname+i;
if (eval(name).flag==1){
eval(name).flag*=-1;
eval(name).flag==1?eval(name).setColor(eval(name)._flagname,eval(name).colon):
eval(name).setColor(eval(name)._flagname,eval(name).coloff);

}
}
}

stop();

А в мувик movbtn добавим обращение к этой процедуре:

on (release) {
_root.turnButtonsOff(this.numBtns,this.Fullname);
this.press();
}

Вот где собака-то зарыта! При нажатии любой из кнопок теперь будет выполняться
проверка всех кнопок блока, включенная - выключится, нажатая - включится.

Запускаем еще раз наш проект и радуемся полученному эффекту. Задача решена!

Можно поэкспериментировать, добавив в blockbtn еще один экземпляр кнопки (с именем bu0)
и продублировать и его. Получим, как в моем примере, два независимо работающих
кнопочных блока.

color1=0x3399cc;
color2=0xcc9933;

capt=new array("Кот","Пес","Корова","Лошадь","Коза");
capt2=new array("Слон","Муха","Оса","Овод");
movbtn0.makeButtonBlock(4,0,0,0,0,20,"caption",capt2,0,"flagball",color1,color2);

bu0.makeButtonBlock(5,5,-100,0,0,30,"caption",capt,0,"flagball",color1,color2);

stop();
Обратите внимание, во втором блоке я начинаю нумерацию кнопок с пяти. А предыдущие
номера кнопок были 0-4.
Просто, а? Не нужно даже особенно понимать, как это работает, единственное условие -
снабдить кнопки необходимыми заголовками и флажками, да не забыть их имена!
Что же, напишем обработчик. Простенький.

function doSomething(bun){
if (bun==0){gotoandstop(2)} else
if (bun==1){_root.gotoandstop(3)} else
if (bun==2){_root.gotoandstop(4)} else
if (bun==3){_root.gotoandstop(5)}else
if(bun==4){_root.gotoandstop(6)};
}
Поместим его в первый кадр сцены.
А обращение к обработчику добавим в событие нашей кнопки:

on (release) {
_root.turnButtonsOff(this.numBtns,this.Fullname);
this.press();
_root.doSomething(_root.bun);
}
Здесь я специально использовал в качестве номера кнопки глобальную переменную.
Должно же хоть что-то быть снаружи!
Да, а как же вычислить номер кнопки?
Придется дополнить наш прототип в файле bb.as:

movieClip.prototype.press=function(){
this.flag*=-1;
this.flag==1?this.setColor(this._flagname,this.colon):this.setColor(this._flagname,this.coloff);
l=length(this._name);
lb=length(this.basename);
this.buttonnumber=this._name.substr(lb,l-lb);
_root.bun=number(this.buttonnumber);
}

Вот теперь - уж точно, все.
Для проверки добавим в сцену 5 фреймов, в каждый из которых что-нибудь поместим.
У меня это - просто тексты "раз, два, три, четыре, пять".
Проверяем.
Работает!

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

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

Загрузить файлы! Загрузите файлы использованные в уроке (zip 24 кб,)



Литература по FLASH