Основно съдържание
Програмиране
Функция за бутон
Ако мина през курса въведение в JS, значи вече направи няколко бутона в Logic предизвикателствата Твоят първи бутон и По-умен бутон. В случай, че не си спомняш, нека да си припомним как се правят прости бутони.
Първо какви са минималните характеристики на един бутон?
- Форма на платното (обикновено правоъгълник)
- Етикет или иконка, която да описва какво ще прави
- Отговор на кликване от потребителя върху бутона (но не и другаде)
Можем да постигнем #1 и #2 доста лесно:
fill(0, 234, 255);
rect(100, 100, 150, 50, 5);
fill(0, 0, 0);
textSize(19);
text("Безполезен бутон", 110, 133);
За да постигнем #3, трябва да дефинираме функцията
mouseClicked
, която ще се извика, когато потребителят кликне, а в нея трябва да проверим дали mouseX
и mouseY
са в границите на бутона. За бутона, даден по-горе, границите му са от x=100 до x=250 и от y=100 до y=150, както е показано по-долу:Можем да проверим тези координати, като свържем четирите условия с оператора
&&
:mouseClicked = function() {
if (mouseX >= 100 && mouseX <= 250 &&
mouseY >= 100 && mouseY <= 150) {
println("Все още доста безполезен");
}
};
Опитай да кликнеш върху него, за да се увериш, че работи:
Определено работи, но нещо ме притеснява. Притеснявам се за това, че кодът ми не е преизползваем. Колко работа трябва да свърша, ако искам да променя позицията на бутона? (Опитай!) Виждам доста "хард-коднати" (представени чрез себе си) числа в кода си – като координатите във функцията
mouseClicked
, и веднага започвам да се чудя дали няма по-чист начин.За начало, нека изнесем в променливи позицията и размера, за да можем да ги променяме на едно място и да сме сигурни, че щракането върху бутона ще продължи да работи. Добавих
btnX
, btnY
, btnWidth
и btnHeight
към програмата по-долу. Опитай да промениш стойностите им и да кликнеш върху бутона:Така вече е по-добре. Но все още трябва да свърша доста работа, ако искам да добавя още един бутон. Трябва ли да копирам всичко това и да направя
btn2X
, btn2Y
? Ух, това не звучи никак забавно. Звучи ми като добра мотивация да напиша функция, която да се грижи за всичко, което е еднакво за бутоните, и да използва параметри за нещата, които са различни. Можем да го запишем така, като превърнем променливите в параметри:var drawButton = function(btnX, btnY, btnWidth, btnHeight) {
fill(0, 234, 255);
rect(btnX, btnY, btnWidth, btnHeight, 5);
fill(0, 0, 0);
textSize(19);
textAlign(LEFT, TOP);
text("Безполезен бутон", btnX+10, btnY+btnHeight/4);
};
След това я извикваме така:
drawButton(100, 100, 150, 50);
Но, виж ти, какво става с кода в нашата функция
mouseClicked
? Виждаш ли какъв проблем ще имаме с него?mouseClicked = function() {
if (mouseX >= btnX && mouseX <= (btnX+btnWidth) &&
mouseY >= btnY && mouseY <= (btnY+btnHeight)) {
println("Все още безполезен");
}
};
Ако съберем този код, ще получим грешка от нашия приятел О Не, която гласи "btnX is not defined" ("btnX не е дефиниран") – и той ще е прав! Превърнахме
btnX
в параметър, което означава, че вече не е глобална променлива. Това е чудесно, когато искаме да преизползваме функцията drawButton
, но сега функцията mouseClicked
не знае кои координати да проверява.Значи трябва да намерим начин да подаваме информацията на
drawButton
и тази информация да е достъпна за mouseClicked
. Хрумват ми няколко варианта:- Отново инициализираме глобалните променливи за позицията и размера (
btnX, btnY, btnWidth, btnHeight
) - Инициализираме глобален масив, който да съхранява всички параметри (
var btn1 = [...];
) - Инициализираме глобален обект, който да пази параметрите (
var btn1 = {..}
) - Използваме принципите на обектно-ориентираното програмиране, за да дефинираме бутона и да запазим неговите свойства (
var btn1 = new Button(...))
Кое да изберем? Първата възможност не ми харесва, защото ще трябва да добавим страшно много глобални променливи, а аз имам алергия към глобалните променливи. Не харесвам втория подход, защото е трудно да се чете код, който взима данни с индекси от масив. Третият подход ми харесва, защото в него има само една глобална променлива и ще получим по-четим код. Харесвам и четвъртата възможност: да използваме принципите на обектно-ориентираното програмиране, за да създадем общ тип
Button
и да създаваме обекти от него, но ще запазя това за по-късно.Можем да създадем нашия глобален обект
btn1
ето така:var btn1 = {
x: 100,
y: 100,
width: 150,
height: 50
};
Променяме функцията
drawButton
така, че да приема един обект, от който взима свойствата:var drawButton = function(btnX, btnY, btnWidth, btnHeight) {
fill(0, 234, 255);
rect(btnX, btnY, btnWidth, btnHeight, 5);
fill(0, 0, 0);
textSize(19);
textAlign(LEFT, TOP);
text("Безполезен бутон", btnX+10, btnY+btnHeight/4);
};
Функцията
mouseClicked
ще проверява свойствата на глобалната променлива:mouseClicked = function() {
if (mouseX >= btn1.x && mouseX <= (btn1.x+btn1.width) &&
mouseY >= btn1.y && mouseY <= (btn1.y+btn1.height)) {
println("Все още безполезен");
}
};
Опитай по-долу! Както и преди, нека променим различни параметри на бутона и да видим кое как ще работи:
Идеята на работата дотук беше да направим така, че да можем да добавяме още бутони – добър тест за повторно използване на елемент. Можем ли да го направим? Да пробваме!
Ще започнем с нова глобална променлива,
btn2
, ще я отместим в посока Y от първия бутон:var btn2 = {
x: 100,
y: 200,
width: 150,
height: 50
};
След това ще нарисуваме бутона:
drawButton(btn2);
Това ще нарисува 2 бутона на платното, но само първият отговаря на кликване. Можем да накараме и втория да реагира, като използваме логиката и подадем
btn2
вместо btn1
, ето така:mouseClicked = function() {
if (mouseX >= btn1.x && mouseX <= (btn1.x+btn1.width) &&
mouseY >= btn1.y && mouseY <= (btn1.y+btn1.height)) {
println("Все още безполезен");
}
if (mouseX >= btn2.x && mouseX <= (btn2.x+btn2.width) &&
mouseY >= btn2.y && mouseY <= (btn2.y+btn2.height)) {
println("Втори все още безполезен!");
}
};
Но цялото това повтаряне на код не те ли кара да сбърчиш нос? Нека си направим функция
isMouseInside
, която знае как да проверява всеки обект бутон, и която връща true, ако мишката е върху него:var isMouseInside = function(btn) {
return (mouseX >= btn.x &&
mouseX <= (btn.x+btn.width) &&
mouseY >= btn.y &&
mouseY <= (btn.y+btn.height));
};
И сега можем да използваме функцията в
mouseClicked
, за да редуцираме количеството код, който се повтаря:mouseClicked = function() {
if (isMouseInside(btn1)) {
println("Все още безполезен");
} else if (isMouseInside(btn2)) {
println("Втори все още безполезен!");
}
};
И това е! Използвахме функции, за да нарисуваме няколко бутона и направихме така, че сравнително лесно да добавяме още бутони. Опитай и ти:
Можем да продължим – да направим масив от всички бутони в програмата, което ще ни позволи да ги променяме лесно с надписи и цветове – но се надявам, че това ти даде добра основа за това как да създаваш прости бутони с помощта на функции. Следва да научим как да създаваме бутони, като използваме принципите на обектно-ориентираното програмиране.
Искаш ли да се присъединиш към разговора?
Все още няма публикации.