Como criar um efeito de raspadinha com Vanilla JavaScript

Vamos começar dando uma olhada no que estamos criando. Ao final deste tutorial, você terá algo assim (mova o cursor do mouse sobre o painel de rascunho e observe um código gerado exclusivamente se revelar):

Visão geral

Em HTML, o element é uma ferramenta poderosa para renderizar diretamente gráficos 2D, como imagens, formas e texto, no navegador da web. Fornece uma superfície de desenho que pode ser manipulada através de JavaScript, permitindo-nos criar gráficos dinâmicos e interativos. Vamos contar com elementos neste tutorial.

Começaremos criando um elemento card exibindo um código aleatório. A seguir, criaremos uma tela com as dimensões exatas do elemento cartão. Esta tela será sobreposta ao elemento cartão, ocultando o número abaixo dele.

Para simular o efeito scratch-off, usaremos o globalCompositeOperation propriedade do contexto da tela. Ao definir ctx.globalCompositeOperation = "destination-out," partes da tela serão apagadas quando o usuário mover o mouse sobre a tela. O código no cartão será revelado gradualmente à medida que o usuário riscar (mover o mouse) continuamente sobre a tela.

Estrutura HTML

A estrutura HTML usando Bootstrap ficará assim:

1
 class="d-flex flex-column align-items-center justify-content-center vh-100">
2
 class="text-center mb-5">Scratch Below
3
  
4
   class="fas fa-arrow-down fa-6x mb-4">
5
   class="row mt-5">
6
     class="col-md-4 col-sm-6 col-8">
7
       id="card" class="mx-auto border position-relative bg-white">
8
         id="code" class="text-center">
9
        
10
          class="position-absolute top-0 start-0"
11
          id="scratch-pad"
12
        >
13
      
14
    
15
  
16

O O elemento é posicionado no topo do elemento card usando a classe position-absolute junto com top-0 e start-0. Esses estilos garantem que ele comece no canto superior esquerdo do elemento pai.

Adicione o link Bootstrap CDN no seu documento HTML seção.

1

2
  href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
3
  rel="stylesheet"
4
  integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
5
  crossorigin="anonymous"
6
/>

Estilos CSS personalizados

Adicione uma fonte personalizada e uma cor de fundo ao corpo da página.

1
@import url("https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap");
2
body {
3
    font-family: "DM Mono", monospace;
4
    background-color: #f3f1f5;
5
}

O elemento cartão terá as seguintes dimensões

1
  #card {
2
    width: 400px;
3
    height: 90px;
4

5
  }

Adicione os seguintes estilos ao elemento de código, que exibirá os caracteres aleatórios.

1
#code {
2
    font-size: 50px;
3
    padding: 20px;
4
    background-color: white;
5
    line-height: 40px;
6
    font-weight: 800;
7
  }

Cursor personalizado

Em CSS, a propriedade cursor controla a aparência do ponteiro do mouse quando ele passa sobre um elemento. Embora o valor padrão do cursor seja um ícone de mão, você também pode personalizar o cursor especificando uma imagem usando o botão url valor. Isso permite que você crie uma experiência de rolagem única. Vamos definir nosso cursor personalizado.

1
canvas {
2
cursor: url("https://essykings.github.io/JavaScript/coin42.png") 50 50,
3
  crosshair;
4
}

No nosso caso, estamos usando esta moeda (baixada de uma das renderizações de moeda 3D do ga-analytics#sendElementsClickEvent”>Envato) como cursor.

Crie personagens aleatórios

Para garantir que os caracteres revelados após o scratching sejam únicos, criaremos uma função para gerar um caractere aleatório cada vez que o aplicativo for carregado. Crie uma função chamada generateRandomString() e adicione o código abaixo.

1
function generateRandomString(length) {
2
    const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
3
    let code = "";
4
    for (let i = 0; i < length; i++) {
5
        code += characters.charAt(
6
        Math.floor(Math.random() * characters.length)
7
      );
8
    }
9
    return code;
10
  }

No código acima:

  • const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; define uma variável de caracteres que contém as letras maiúsculas do alfabeto (AZ) e os dígitos (0-9).
  • let code = "; inicializa uma string vazia para armazenar a string de caracteres final.
  • Para o loop for, um número aleatório será gerado e armazenado na variável de código em cada iteração,

Atualize o conteúdo de texto do elemento de código para mostrar o caractere gerado.

1
document.getElementById("code").textContent = generateRandomString(12);

O aplicativo até agora está assim:

A próxima etapa é desenhar na tela para ocultar o conteúdo do elemento cartão.

Desenhar tela

Primeiro, pegue a tela e defina a largura e a altura para serem iguais às do elemento cartão.

1
const canvas = document.getElementById("scratch-pad");
2
canvas.width = card.offsetWidth;
3
canvas.height = card.offsetHeight;

A seguir, obtenha o contexto da tela. Um objeto de contexto é onde os desenhos serão renderizados.

1
const ctx = canvas.getContext("2d");

A próxima etapa é preencher a tela com uma cor gradiente personalizada para ocultar o conteúdo do elemento cartão. Para criar o gradiente, inicialize uma instância de gradiente usando o createLinearGradient() método.

1
 const gradient = ctx.createLinearGradient(
2
        0,
3
        0,
4
        canvas.width,
5
        canvas.height
6
      );

O gradiente começa no canto superior esquerdo (0, 0) e termina no canto inferior direito (onde termina a tela).

Agora que temos um gradiente, podemos especificar as cores que aparecerão no gradiente.

1
gradient.addColorStop(0, "#DFBD69");
2
gradient.addColorStop(1, "#926F34");
3
ctx.fillStyle = gradient;

ctx.fillStyle informa ao contexto o que usar ao desenhar; neste caso, um gradiente marrom dourado será usado para preencher as formas desenhadas na tela.

Por fim, preencha toda a tela com a cor gradiente desenhando um retângulo em toda a tela.

1
  ctx.fillRect(0, 0, canvas.width, canvas.height);

Até agora temos isto:

Efeito de raspar

A última etapa é implementar o efeito scratch-off. Defina uma variável chamada isDrawing; esta variável monitorará se estamos desenhando na tela. Inicialmente a variável será definida como falsa

Em seguida, precisamos definir ouvintes de eventos para movimentos do mouse para capturar eventos de mouse e toque. Quando o usuário move o mouse ou usa o dedo para tocar na tela (em telas sensíveis ao toque), o efeito de scratch será implementado.

1
canvas.addEventListener("mousemove", (e) => {
2
isDrawing = true;
3

4
});
5

6

7
canvas.addEventListener("touchstart", (e) => {
8
isDrawing = true;
9

10
});
11

12
canvas.addEventListener("touchmove", (e) => {
13

14
}
15
});
16

Aqui está um resumo dos eventos de mouse e toque:

  • mousemove evento: durante este evento, o isDrawing variável é definida como verdadeira, sinalizando que o desenho deve começar.
  • touchstart evento: durante este evento o isDrawing variável é definida como verdadeira, indicando o início de um desenho baseado em toque.
  • touchmove evento: Implementaremos o efeito scratch durante o touchmove evento (ou seja, quando um usuário move o dedo na tela).

Vamos implementar cada evento de forma independente; começaremos com o evento de movimento do mouse. Quando começar a usar o movimento do mouse, queremos que o efeito de scratch seja aplicado na tela.

Crie o scratch() função, que será chamada quando o usuário começar a desenhar.

1
function scratch(e) {
2

3
}

No scratch() função, calcule a posição do mouse ou evento de toque em relação à tela usando getBoundingClientRect(). O getBoundingClientRect() O método é útil para obter a posição de um elemento em relação à janela de visualização. No nosso caso, queremos obter a posição do mouse ou do toque em relação à tela.

Para obter a posição do mouse ou do toque em relação à tela, subtraímos a posição da tela das coordenadas do evento:

1
function scratch(e) {
2
    const rect = canvas.getBoundingClientRect();
3
    const x = e.clientX - rect.left;
4
    const y = e.clientY - rect.top;
5
}

Defina a operação composta como destination-out; Isso significa que qualquer coisa desenhada na tela apagará o que já estiver na tela ou a tornará transparente. Quando a tela for apagada, o conteúdo do elemento cartão será revelado.

Um círculo com raio de 20 pixels será desenhado, criando efetivamente um “arranhão” efeito na tela. Atualize a função da seguinte maneira.

1
function scratch(e) {
2
    const rect = canvas.getBoundingClientRect();
3
    const x = e.clientX - rect.left;
4
    const y = e.clientY - rect.top;
5

6
    ctx.globalCompositeOperation = "destination-out";
7
    ctx.beginPath();
8
    ctx.arc(x, y, 20, 0, Math.PI * 2, false);
9
    ctx.fill();
10
  }
  • ctx.beginPath(); inicia um caminho de desenho
  • ctx.arc(x, y, 20, 0, Math.PI * 2, false); desenha um caminho circular (um arco) com um raio de 20 pixels começando na posição do mouse
  • ctx.fill() preenche o círculo, apagando efetivamente a parte da tela coberta pelo arco circular.

Agora, atualize as funções de eventos do mouse. Ao mover o mouse, definiremos isDrawing para true para indicar que o desenho foi iniciado e, em seguida, invocar a função scratch() para iniciar o apagamento conforme o mouse se move.

1
canvas.addEventListener("mousemove", (e) => {
2
isDrawing = true;
3
scratch(e);
4
});

Atualize o touchstart e touchmove eventos da seguinte forma: da seguinte forma.

O efeito de arranhão começará quando um toque começar. e.touches[0] refere-se ao primeiro ponto de contato. À medida que o usuário move os dedos pela tela em dispositivos sensíveis ao toque, o efeito de arranhão continuará.

1
canvas.addEventListener("touchstart", (e) => {
2
    isDrawing = true;
3
    scratch(e.touches[0]);
4
  });
5

6
  canvas.addEventListener("touchmove", (e) => {
7
    if (isDrawing) {
8
      scratch(e.touches[0]);
9
    }
10
  });

Conclusão

Criamos com sucesso um efeito de raspar realista usando JavaScript vanilla! Este aplicativo mostrou o quão poderoso é o HTML5 O elemento pode ser a criação de experiências de usuário envolventes e interativas. Abaixo está um lembrete do produto final.

Deixe uma resposta