Poli.school
Animações

Eventos

As funções setup() e draw(), variáveis locais e globais, animações e tratamento de eventos de mouse e teclado em p5.js

Interagindo com a Tela Gráfica

Para interagir com a tela gráfica precisaremos usar algum dispositivo de entrada. Por enquanto usaremos o mouse e o teclado, mas é possível usar outros dispositivos, como por exemplo o microfone ou a câmera, para enviar informações ao computador. Uma interação deve possuir ação e reação, não bastando passarmos informações ao programa. É essencial que tenhamos feedback, ou seja, que vejamos os efeitos de nossas ações no comportamento do programa, de preferência instantaneamente. Esse feedback pode ser sonoro, textual e/ou na forma de imagem (eventualmente também na forma de movimentos físicos, como no caso de um robô ou de outros equipamentos controlados pelo computador). Usaremos a função draw() para dar retorno visual, ao atualizar o conteúdo da tela gráfica em função das ações do usuário. Como a draw() é executada 60 vezes por segundo, as respostas a essas ações serão visualizadas instantaneamente. Para obter as ações executadas pelo usuário, via mouse e/ou teclado, usaremos as funções que tratam os eventos (movimentos, cliques, acionamentos de tecla) desses dispositivos.

Funções de tratamento de eventos: Teclado e Mouse

Uma função que trata eventos é disparada sempre que ocorre uma situação específica à qual esteja vinculada. Dois exemplos desse tipo de função são as já conhecidas setup() e draw(). A primeira, está vinculada ao evento de início de execução do programa. Assim, sempre que um programa é executado a setup() é acionada. Como esse evento (início de execução) só ocorre uma vez a cada execução do programa, a setup() é executada uma única vez também. Já a função draw() está associada a um contador de tempo, que na configuração default dispara um evento a cada 1/60 de segundo. Dessa forma a draw() é executada ininterruptamente 60 vezes por segundo.

As funções de tratamento de eventos inicialmente não possuem conteúdo. Cabe ao programador escrever a sequência de comandos que deseja sejam executados a cada vez que determinado evento de seu interesse ocorra. E esse conteúdo deve ser escrito num bloco que especifica a função correspondente àquele evento, conforme já visto para as funções setup() e draw():

function nomeDaFuncao() {
  // comandos que serão executados quando ocorrer o evento associado
  // a essa função
}

O p5.js inclui algumas outras funções que são executadas automaticamente, além da setup() e draw(). Entre elas estão funções para o tratamento de comandos de teclado e mouse, conforme resumido na lista a seguir:

Funçãoexecutada automaticamente quando...
keyPressed()Uma tecla do teclado é pressionada
keyReleased()Uma tecla do teclado para de ser pressionada
keyTyped()Uma tecla do teclado é pressionada e liberada
mouseClicked()Um botão do mouse é pressionado e liberado
mouseDragged()O mouse é movimentado com um botão pressionado
mouseMoved()O mouse é movimentado sem nenhum botão pressionado
mousePressed()Um botão do mouse é pressionado
mouseReleased()Um botão do mouse deixa de ser pressionado
mouseWheel()A roda do mouse é rotacionada

Todas essas funções têm exatamente o mesmo nome em p5.js.

Exemplo: Tratamento de evento de mouse

Suponha que se deseja desenhar uma bolinha na tela, na posição do mouse, toda vez que esse for clicado. Uma forma simples de fazer isso é programar a função de tratamento de evento mouseClicked() para que faça o desenho de um círculo na posição do mouse. Toda vez que o mouse for clicado será gerado o evento "mouseClicked" e a função correspondente mouseClicked() será executada. Como a programamos para desenhar um círculo na posição do mouse, obteremos o efeito desejado. Execute o código a seguir e confira (clique dentro do canvas).

Código 4.5 - Desenhando um círculo a cada clique do mouse
function setup() { // executada automaticamente no início de execução do programa
  createCanvas(500, 500);
  background(0); // fundo preto
}

function draw() { // mesmo vazia é necessária para que a janela seja redesenhada
}

function mouseClicked() { // executada automaticamente sempre que o mouse for clicado
  // desenha círculo de 20 pixels na posição do mouse
  circle(mouseX, mouseY, 20);
}
Carregando sketch…

Como você pode observar, não há nada dentro da função draw() e mesmo assim você consegue gerar uma janela interativa. Entretanto, é importante ressaltar que, de qualquer forma, é necessário que ela seja escrita mesmo vazia, pois só assim a janela será redesenhada e refletirá as eventuais ações executadas pelas outras funções de tratamento de eventos.

Atividade 5

Escreva um programa que desenha bolinhas brancas enquanto o mouse for movido com botão pressionado (mouseDragged) e limpa a tela quando o botão do mouse for solto (mouseReleased).

Exemplo: Tratamento de evento de teclado

Vamos testar o funcionamento da função keyTyped(). Toda vez que uma tecla é pressionada essa função é disparada. Mas para que algo aconteça, como por exemplo, mostrar na tela o que foi digitado, é necessário escrever o programa a ser executado pela keyTyped(). O caractere da última tecla pressionada pode ser obtido na variável automática de sistema key. Diferente do Processing, em p5.js a variável key já é diretamente um texto (String), então não é preciso nenhuma conversão para usá-la em text(). Execute o programa a seguir para testar a função que trata o evento de digitar no teclado.

Código 4.6 - Mostrando a tecla digitada na posição do mouse
function setup() {
  createCanvas(500, 300);
  background(0);
}

function draw() { // mesmo vazia é necessária para que a janela seja redesenhada
}

// função executada quando uma tecla é pressionada e liberada
function keyTyped() {
  // imprime a tecla digitada na posição do mouse
  text(key, mouseX, mouseY);
}
Carregando sketch…

Atividade 6

Elabore um programa que escreve na tela os caracteres que são digitados, iniciando na posição (0,50) e adicionando 10 pixels na posição x a cada caractere digitado.

Variáveis automáticas de entrada

Para muitas situações, podemos simplesmente utilizar as variáveis automáticas do p5.js, tais como mouseX, mouseY, mouseIsPressed, mouseButton, keyIsPressed, key e keyCode dentro da função draw() para responder a comandos do usuário. Essas variáveis são úteis quando precisamos responder de forma mais imediata ou, ainda, armazenar sequências de comandos, pois elas só armazenam a última tecla ou botão pressionados.

Atenção — diferença importante em relação ao Processing

No Processing, a variável booleana que indica se uma tecla está pressionada se chama keyPressed, mesmo nome da função de evento keyPressed() — o que é possível porque Java trata variáveis e funções em espaços de nomes diferentes. Em JavaScript isso causaria um conflito, já que uma função é armazenada numa variável comum. Por isso, o p5.js renomeou essa variável booleana para keyIsPressed. O mesmo vale para o mouse: a variável booleana chama-se mouseIsPressed, em vez de mousePressed, que continua sendo o nome da função de evento.

Para ilustrar esses conceitos, vamos comparar dois programas. No primeiro, vamos escrever na janela a tecla que o usuário está pressionando, usando as variáveis automáticas.

Código 4.7 - Uso da variável keyIsPressed (com efeito colateral indesejado)
let x = 0;

function setup() {
  createCanvas(500, 300);
  background(0);
}

function draw() {
  // existe tecla apertada?
  if (keyIsPressed) {
    // escreve na tela
    text(key, x, 50);
    x = x + 10;
  }
}
Carregando sketch…

Se executarmos esse programa, veremos que cada tecla pressionada é repetida várias vezes na tela. A razão para isso é que a função draw() é executada 60 vezes por segundo, portanto mais rapidamente que o tempo que um humano leva para pressionar e soltar uma tecla. O que queremos, na verdade, é detectar cada tecla que foi pressionada e atualizar a tela somente uma vez. Isso pode ser feito com o programa a seguir.

Código 4.8 - Detectando cada tecla digitada uma única vez
let x = 0;
let tecla = "";

function setup() {
  createCanvas(500, 300);
  background(0);
}

// função executada quando uma tecla é pressionada e liberada
function keyTyped() {
  // memoriza a tecla que foi digitada
  tecla = key;
}

function draw() {
  // existe tecla apertada?
  if (tecla !== "") {
    // escreve na tela
    text(tecla, x, 50);
    // "esquece" a tecla que já foi desenhada na tela
    tecla = "";
    x = x + 10;
  }
}
Carregando sketch…

Saiba mais sobre escrever textos e números na janela gráfica

Você pode alterar o tamanho da fonte usando o comando textSize, a cor através do comando fill e o alinhamento do texto através do comando textAlign.

Na seção anterior, escrevemos o texto a ser desenhado na tela diretamente no comando text. No entanto, também é possível armazenar texto em variáveis. O programa a seguir mostra o uso de uma variável desse tipo, além de uma fonte carregada de um arquivo. Diferente do Processing (que usa o formato proprietário .vlw, gerado a partir do menu Tools → Create Font), em p5.js as fontes são carregadas diretamente de arquivos .ttf ou .otf, dentro da função preload(), que garante que a fonte termine de carregar antes do setup() ser executado.

let f;

function preload() {
  f = loadFont('minhafonte.ttf');
}

function setup() {
  createCanvas(500, 200);
  background(0);
  fill(255);
  textFont(f);
  let t;
  t = "teste 1 2 3";
  text(t, 50, 50);
}

Observe que o conteúdo a ser atribuído para a variável t é indicado entre aspas. Isso é necessário para identificar os limites do texto, caso contrário não haveria como determinar o que é texto e o que é programa.

Textos em JavaScript possuem alguns recursos adicionais em relação a outros tipos de variáveis. Por exemplo, se a variável t guarda um texto, podemos usar a propriedade t.length (sem parênteses, pois é uma propriedade, não uma função) para obter o comprimento do texto (em número de caracteres). Também podemos utilizar a função t.substring() para obter uma parte do texto original, exatamente como no Processing, como ilustrado nos exemplos abaixo:

let t;
t = "teste 1 2 3";
let c;
c = t.length; // c irá receber o valor 11 (propriedade, sem parênteses)
let w;
w = t.substring(0, 5); // w irá receber o valor "teste"
let k;
k = t.substring(6, 11); // k irá receber o valor "1 2 3"

A figura abaixo ajuda a entender os parâmetros do comando substring: "cortamos uma fatia" do texto original entre as duas posições passadas para o comando. É importante observar que a contagem começa do zero, que corresponde à posição do primeiro caractere do texto. Da mesma forma, a "fatia" não inclui o caractere indicado na posição final.

É possível utilizar a operação de adição (+) para agrupar dois ou mais textos, exatamente como no Processing. Veja o exemplo abaixo:

Código 4.9 - Concatenando textos com o operador +
function setup() {
  createCanvas(200, 200);
  background(0);
  fill(255);
  let a;
  a = "teste";
  let b;
  b = " 1 2 3";
  let c;
  c = a + b; // o sinal + indica concatenação de textos
  text(c, 30, 30);
}
Carregando sketch…

É possível também utilizar a operação de adição para agrupar texto (entre aspas) com conteúdos de variáveis numéricas, que são automaticamente convertidas para texto — assim como no Processing.

Código 4.10 - Concatenando texto com um valor numérico
function setup() {
  createCanvas(200, 200);
  background(0);
  fill(255);
  let x, a, b;
  a = 11;
  b = 7;
  x = a - b;
  text("a subtração é " + x, 50, 50);
}
Carregando sketch…

��������������������������������������������������������

Copyright © 2026