Conteúdo principal
Programação
Uma função botão
Se você passou pelo curso Introdução ao JS, já criou alguns botões simples nos desafios de lógica Seu Primeiro Botão e Um Botão Mais Inteligente. Caso tenha esquecido, vamos retomar como fazer um botão simples.
Primeiro, quais são os requisitos mínimos de um botão?
- Uma forma na tela (normalmente um retângulo)
- Inclui um rótulo ou ícone que descreve o que ele faz
- Responde aos cliques nele (mas não em outro lugar)
Podemos cobrir os requisitos 1 e 2 facilmente:
fill(0, 234, 255);
rect(100, 100, 150, 50, 5);
fill(0, 0, 0);
textSize(19);
text("Useless button", 110, 133);
Para cobrir o requisito 3, precisamos definir uma função
mouseClicked
que será chamada quando o usuário clicar. Dentro dela, precisamos verificar se mouseX
e mouseY
estão dentro da caixa delimitadora do botão. Para o botão acima, ela estende-se de x=100 até x=250, e de y=100 até y=150, conforme ilustrado abaixo:Podemos verificar as coordenadas utilizando
&&
para unir as quatro condições:mouseClicked = function() {
if (mouseX >= 100 && mouseX <= 250 &&
mouseY >= 100 && mouseY <= 150) {
println("Ainda continua inútil");
}
};
Tente clicar no botão e na área em volta para ver se ele funciona:
Ele definitivamente funciona, mas isso também me preocupa. Estou preocupado por não ser código muito reutilizável. Quanto trabalho eu terei se quiser mudar o botão de posição? (Experimente acima!) Eu vejo muitos números fixados no código – como as coordenadas na função
mouseClicked
, o que imediatamente me leva a pensar se não há uma maneira mais simples de fazer isso. Para começar, vamos criar variáveis para a posição e tamanho, de forma que possamos mudar esses valores em um só lugar e, mesmo assim, manter o clique funcionando. Eu adicionei
btnX
, btnY
, btnWidth
e btnHeight
ao programa abaixo. Experimente mudar seus valores e clicar no botão:Bem, assim está melhor. No entanto, quanto trabalho terei se quiser adicionar mais um botão? Tenho que copiar e colar tudo aquilo, e criar
btn2X
, btn2Y
? Ah, isso não parece muito divertido. Isso parece um bom motivo para escrever uma função que se encarregará de fazer tudo que for igual para os botões, e usará parâmetros para lidar com o que for diferente. Nós poderíamos escrevê-la assim, transformando as variáveis em parâmetros: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("Useless button", btnX+10, btnY+btnHeight/4);
};
Então, chamamos a função assim:
drawButton(100, 100, 150, 50);
Mas, e o nosso código de
mouseClicked
? Vê qual seria o problema com isso?mouseClicked = function() {
if (mouseX >= btnX && mouseX <= (btnX+btnWidth) &&
mouseY >= btnY && mouseY <= (btnY+btnHeight)) {
println("Ainda continua inútil");
}
};
Se tivéssemos todo esse código junto, teríamos um erro de "Oh, não" com "btnX não está definido" - e ele está certo! Nós transformamos
btnX
em um parâmetro de função, o que significa que não é mais uma variável global. Isso é ótimo para a reutilização da função drawButton
, mas, agora, a função mouseClicked
não tem como saber as coordenadas que precisa verificar.Então nós precisamos descobrir uma boa maneira de passar a informação para
drawButton
e disponibilizar essa informação para mouseClicked
. Eu tenho algumas opções:- Criar novamente variáveis globais para a posição e o tamanho (
btnX, btnY, btnWidth, btnHeight
) - Criar um arranjo global que armazena todos os parâmetros (
var btn1 = [...];
) - Criar um objeto global que armazena todos os parâmetros (
var btn1 = {..}
) - Usar princípios de orientação a objetos para definir o botão e armazenar as propriedades (
var btn1 = new Button(...))
Qual escolher? Bem, eu não gosto muito da primeira porque teríamos que adicionar muitas variáveis globais e eu tenho uma alergia a variáveis globais. Eu não amo a segunda técnica porque é difícil ler código que pega dados baseados em índices de arranjos. Gosto da terceira técnica porque ela usa somente uma variável global, e assim o código fica mais legível. Eu também gosto da quarta técnica, que usa princípios orientados a objetos para criar tipos de objeto
Button
genéricos, mas vamos deixar isso para depois.Podemos criar nosso objeto global
btn1
da seguinte forma:var btn1 = {
x: 100,
y: 100,
width: 150,
height: 50
};
E alterar a função
drawButton
para aceitar um único objeto, do qual então pega as propriedades:var drawButton = function(btn) {
fill(0, 234, 255);
rect(btn.x, btn.y, btn.width, btn.height, 5);
fill(0, 0, 0);
textSize(19);
textAlign(LEFT, TOP);
text("Useless button", btn.x+10, btn.y+btn.height/4);
};
A função
mouseClicked
irá verificar as propriedades da variável global:mouseClicked = function() {
if (mouseX >= btn1.x && mouseX <= (btn1.x+btn1.width) &&
mouseY >= btn1.y && mouseY <= (btn1.y+btn1.height)) {
println("Ainda continua inútil");
}
};
Experimente fazer isso! Como antes, tente alterar parâmetros diferentes do botão e ver se ele continua funcionando:
A ideia de fazer isso é que possamos adicionar mais botões com facilidade, o último teste de reusabilidade. Podemos fazer isso?
Vamos começar com uma nova variável global,
btn2
, com deslocamento na direção y do primeiro botão:var btn2 = {
x: 100,
y: 200,
width: 150,
height: 50
};
Em seguida, vamos desenhar esse botão:
drawButton(btn2);
Desse modo, conseguiremos desenhar 2 botões na tela, mas somente o primeiro responderá a cliques. Nós podemos fazer o segundo responder ao duplicar a lógica e substituir
btn2
por btn1
, assim:mouseClicked = function() {
if (mouseX >= btn1.x && mouseX <= (btn1.x+btn1.width) &&
mouseY >= btn1.y && mouseY <= (btn1.y+btn1.height)) {
println("Ainda continua inútil");
}
if (mouseX >= btn2.x && mouseX <= (btn2.x+btn2.width) &&
mouseY >= btn2.y && mouseY <= (btn2.y+btn2.height)) {
println("O segundo também ainda inútil!");
}
};
Mas todo esse código repetido não te deixa de nariz torcido? Vamos criar uma função
isMouseInside
que sabe verificar qualquer objeto de botão e retorna "verdadeiro" se o mouse estiver dentro dele:var isMouseInside = function(btn) {
return (mouseX >= btn.x &&
mouseX <= (btn.x+btn.width) &&
mouseY >= btn.y &&
mouseY <= (btn.y+btn.height));
};
Agora, podemos usar a função dentro de
mouseClicked
para reduzir drasticamente a quantidade de código repetido:mouseClicked = function() {
if (isMouseInside(btn1)) {
println("Ainda continua inútil ");
} else if (isMouseInside(btn2)) {
println("2nd one still quite useless!");
}
};
Aí está! Usamos funções para desenhar vários botões, e ficou relativamente fácil adicionar novos botões. Tente fazer isso abaixo:
Poderíamos continuar – criando arranjos de todos os botões de um programa, tornando possível personalizar o texto e a cor de um botão – mas espero que o que foi feito já tenha te dado uma boa base para criar botões simples usando funções. Em seguida, vamos percorrer passo a passo a criação de botões usando princípios orientados a objeto.
Quer participar da conversa?
- Porque só escrevemos btn e não btn1?(1 voto)
- btn1 te ajuda a identificar qual botão é qual, poderia ser apenas btn, mas para facilitar a nomeação de cada botão ele coloca apenas btn1, btn2 etc... assim facilitando a nomeação(1 voto)