RSS
Pitang Labs

01 noviembre de 2022

min para ler
Compartilhe

Realidade Aumentada: crie um Business Card interativo utilizando Mind AR e A-frame JS.

Nathalia Lima e Anne Livia Macedo, Desenvolvedoras de Software no Pitang Labs, falam sobre realidade aumentada e auxiliam na criação de um business card interativo utilizando Mind AR e A-frame JS.

Está no ar o Intervalo Técnico sobre Realidade Aumentada! 

A seguir, o tutorial da criação do Business Card em formato de texto:

O que é Mind-AR e A-Frame?

O A-Frame é um framework que permite a elaboração de cenas virtuais através de HTML, permitindo a criação de experiências de realidade aumentada (RA) e realidade virtual (VR), provendo acesso total à API do three.js

O MindAR é uma biblioteca Javascript Open Source de realidade aumentada  (RA) para web, que suporta rastreamento de imagem e rastreamento de rosto, utilizando a gpu (através do webgl) e web worker para aumentar o desempenho.

Configuração inicial

Para esse projeto precisaremos de um index.html que conterá o código principal da aplicação para a construção e exibição da cena virtual. Além disso, serão necessários alguns recursos gráficos, como o target e os elementos virtuais que farão parte da experiência de RA. Desse modo, estruturamos o diretório da seguinte forma:

Criando o target

Criaremos o cartão de visitas que servirá como gatilho para a exibição dos conteúdos interativos da nossa aplicação. É importante, quando estiver fazendo o seu, levar em consideração aspectos que garantam o máximo de feature points possíveis, que permitam maior precisão durante a detecção e rastreamento do alvo em tempo real. O MindAR fornece algumas dicas para que você possa fazer o design ou escolher imagens com esse propósito. Disponibilizamos o seguinte template canvas que iremos utilizar: 

                                                    Figura 1: Cartão de Visita.

Faremos uso do Image Targets Compiler para transformar o Cartão de Visitas em um target. Essa compilação retornará um arquivo targets.mind que armazena os dados das características (features points) em formato compacto. Salve a imagem do seu cartão de visita no formato PNG e o arquivo compilado na pasta targets.

                                  Figura 2: Pontos de características no Target

No index.html, precisaremos importar três bibliotecas que irão permitir a implementação da aplicação usando o MindAR em conjunto com o A-frame. Para importar por meio de CDN, adicione no head do seu index.html: mindar-image.prod.js, mindar-image-aframe.prod.js e aframe.min.js. Então o código inicial poderá estar dessa forma:

<!DOCTYPE html>
<html lang="pt-br">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="<https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.1.4/dist/mindar-image.prod.js>"></script>
    <script src="<https://aframe.io/releases/1.2.0/aframe.min.js>"></script>
    <script src="<https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.1.4/dist/mindar-image-aframe.prod.js>"></script>

    <title>My Business Card - Jane Doe</title>
  </head>

  <body>
  </body>
</html>

Criando a cena

Iniciaremos criando a cena, a a-scene, que é o objeto global da nossa aplicação. Nela iremos especificar algumas propriedades conforme a documentação do MindAR e também adicionar todos os elementos que irão compor o cenário.

<a-scene
  mindar-image="imageTargetSrc: ./assets/target/target.mind;"
  color-space="sRGB"
  renderer="colorManagement: true, physicallyCorrectLights"
  vr-mode-ui="enabled: false"
  device-orientation-permission-ui="enabled: false">
</a-scene>     

 

Propriedades da a-scene:

  • mindar-image: para especificar o caminho para o target compilado. 

  • color-space e renderer: são duas propriedades opcionais que garantem uma maior qualidade na renderização dos elementos gráficos.

  • vr-mode-ui: será inserido para desabilitar o botão que permite acessar a experiência de realidade virtual.

  • device-orientation-permission-ui: será desabilitado para não exibir diálogos que solicitam acesso à alguns eventos relacionados à orientação do dispositivo.

Adicionando elementos na cena

Dentro de a-scene, importaremos os nossos assets através da tag a-assets. Nela podemos colocar imagens, objetos 3D, áudio e vídeos. Para cada elemento importado, devemos indicar um ID único, que é a forma como esse elemento será referenciado mais adiante e o atributo src que conterá o caminho para o item, conforme os exemplos abaixo.  

<a-assets>
  <img id="imagem" src="./imagem.png"/>
  <a-asset-item id="object3D" src="./objeto3D.glft"></a-asset-item>
  <audio id="audio" src="./audio.mp3"></audio>
  <video id="video" src="./video.mp4"></video>
</a-assets>  
    

 

Como iremos inserir imagens na nossa aplicação, precisaremos da tag img. Vamos colocar o nosso primeiro conteúdo que é a imagem do cartão de visitas que você criou.  

<a-assets>
  <img id="businessCard" src="./assets/target/businessCard.png"/>
</a-assets>  
    

 

Agora, vamos inserir a câmera usando a tag a-câmera. Nela colocaremos os seguintes parâmetros iniciais: 

  • position: para setar o posicionamento dessa entidade considerando as coordenadas x, y e z, respectivamente.  

  • look-controls: para desabilitar a opção de rotacionar as entidades através do mouse e touch. 

 

<a-camera
  position="0 0 0"
  look-controls="enabled: false"
>

</a-camera>  

 

Para que possamos exibir o nosso primeiro conteúdo, precisamos da tag a-entity que possibilitará a inserção dos componentes que fornecerão aparência, comportamento e funcionalidades.

Como atributo da tag, precisamos especificar o caminho para o target que precisa ser detectado e rastreado em tempo real. Isso é feito através da propriedade mindar-image-target="targetIndex: 0". O targetIndex: 0, indica o índice da imagem compilada. 

Informação: É possível compilar mais de uma imagem em conjunto. Neste caso, os targets serão referenciados considerando a ordem em que as imagens foram posicionadas no image targets compiler.

<a-entity
  mindar-image-target="targetIndex: 0"
>

</a-entity>

 

Dentro de a-entity, colocamos o conteúdo que queremos exibir. Por ser apenas uma imagem, usando a tag a-image e especificamos os seguintes atributos:

  • id: identificação única do elemento

  • position: considerando as coordenadas x, y, z, podemos posicionar a imagem no centro com os valores 0, 0, 0.

  • height: altura da imagem

  • width: largura da imagem. Sempre que colocamos 1, estamos indicando que é para considerar a largura do target no ambiente real.

  • src: identificador do item que foi carregado na tag a-assets.

 

<a-entity mindar-image-target="targetIndex: 0">
  <a-image
id="card"
      position="0 0 0"
      height="0.552"
      width="1"
      src="#businessCard"
  ></a-image>
</a-entity>

 

Após todos esses procedimentos, o seu index.html, poderá estar conforme o código abaixo. 

<!DOCTYPE html>
<html lang="pt-br">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- Bibliotecas que precisam ser importadas para usar Mindar com A-frame -->
    <script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.1.4/dist/mindar-image.prod.js"></script>
    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.1.4/dist/mindar-image-aframe.prod.js"></script>

    <title>My Business Card - Jane Doe</title>
  </head>

  <body>

    <a-scene
      mindar-image="imageTargetSrc: ./assets/target/target.mind;"
      color-space="sRGB"
      renderer="colorManagement: true, physicallyCorrectLights"
      vr-mode-ui="enabled: false"
      device-orientation-permission-ui="enabled: false"
    >
      <a-assets>
        <img id="businessCard" src="./assets/target/businessCard.png" />
      </a-assets>
     
      <a-camera position="0 0 0" look-controls="enabled: false" ></a-camera>

      <a-entity mindar-image-target="targetIndex: 0">
           
<a-image id="card" position="0 0 0" height="0.552" width="1" src="#businessCard"></a-image>
      </a-entity>
    </a-scene>
  </body>
</html>

 

Vamos executá-lo utilizando o Live Server no seu VS Code.  Após instalar a extensão, clique com o botão direito do mouse sobre o arquivo index.html, e selecione a opção Open with Live Server, que a página web será inicializada. 

                                Figura 3: Exemplo de como usar o Live Server.

Adicionando interações

Podemos começar a colocar o restante dos itens no a-assets. Para isso, baixe esses ícones e coloque na pasta icons e insira uma foto sua, de preferência, com dimensões 980 x 980, na pasta profile. Você pode usar o nosso template canvas para colocar a imagem conforme o design proposto por essa aplicação.

<a-assets>

   <img id="perfil" src="./assets/images/profile/perfil.png" />
  <img id="businessCard" src="./assets/target/businessCard.png" />

  <img id="icon_github" src="./assets/images/icons/icon_github.png" />
  <img id="icon_linkedin" src="./assets/images/icons/icon_linkedin.png" />
  <img id="icon_twitter" src="./assets/images/icons/icon_twitter.png" />
  <img id="icon_web" src="./assets/images/icons/icon_web.png" />
  <img id="icon_email" src="./assets/images/icons/icon_email.png" />
</a-assets>

 

Após importar os elementos no a-assets, organizaremos melhor o nosso código, colocando a imagem do cartão de visitas e a foto agrupadas em uma a-entity. No código, ajustamos o posicionamento, altura, largura e escala das imagens para corresponder ao design elaborado.

<a-entity mindar-image-target="targetIndex: 0">
<a-entity>
        <a-image
            id="card"
            position="-0.0 0.00427 -0.07243"
            height="0.552"
            width="1"
            src="#businessCard"></a-image>
        <a-image
            id="foto-perfil"
            position="0.850 0.0 -0.04426"
            height="0.15"
            width="0.15"
            src="#perfil" 

            scale="4.2 4.2 4.2"
            ></a-image>
        </a-entity>
</a-entity>

 

Dica: Caso você queira ajustar visualmente alguns parâmetros, é possível usar a ferramenta de inspector do A-Frame através do atalho <ctrl> + <alt> + i.

                                      Figura 4: Inspector do A-Frame

Vamos em seguida, inserir uma a-entity contendo cinco tags a-image referentes aos botões dos sites e redes sociais. Experimentalmente, ajustamos os posicionamentos de todos os botões e da entidade que os mantém agrupados, conforme o código abaixo. 

<a-entity position="0.065 -0.002 -0.004">
          <a-image
            id="github-button"
            position="-0.52361 -0.4575 -0.04426"
            height="0.15"
            width="0.15"
            src="#icon_github"
            animation="property: scale; to: 1.1 1.1 1.1; easing: easeInOutQuad; loop: true; dir: alternate"
          >
          </a-image>

          <a-image
            id="linkedin-button"
            position="-0.30772 -0.4575 -0.04426"
            height="0.15"
            width="0.15"
            src="#icon_linkedin"
            animation="property: scale; to: 1.1 1.1 1.1; easing: easeInOutQuad; loop: true; dir: alternate"
          >
          </a-image>
          <a-image
            id="twitter-button"
            position="-0.07819 -0.4575 -0.04426"
            height="0.15"
            width="0.15"
            src="#icon_twitter"
            animation="property: scale; to: 1.1 1.1 1.1; easing: easeInOutQuad; loop: true; dir: alternate"
          >
          </a-image>
          <a-image
            id="email-button"
            position="0.16583 -0.4575 -0.04426"
            height="0.15"
            width="0.15"
            src="#icon_email"
            animation="property: scale; to: 1.1 1.1 1.1; easing: easeInOutQuad; loop: true; dir: alternate"
          >
          </a-image>
          <a-image
            id="web-button"
            position="0.40564 -0.4575 -0.04426"
            height="0.15"
            width="0.15"
            src="#icon_web"
            animation="property: scale; to: 1.1 1.1 1.1; easing: easeInOutQuad; loop: true; dir: alternate"
          >
          </a-image>
        </a-entity>

 

Opcionalmente, inserimos uma animação através da propriedade animation. A animação acontece aumentando o tamanho dos ícones em uma direção alternada. Para mais informações e customizações consulte a documentação oficial do A-frame. 

A escala aumenta e diminui levemente, mas, para exemplificarmos de maneira clara como a animação ocorre, ajustamos um dos ícones para uma maior escala conforme o gif abaixo.

                                        Figura 5: Animação nos botões

 

Após adicionarmos os botões na cena, precisamos permitir as interações, através do clique. Para isso, devemos inserir as propriedades cursor e raycaster na tag a-camera. 

<a-camera
  position="0 0 0"
  look-controls="enabled: false"
  cursor="fuse: false; rayOrigin: mouse;"
  raycaster=" far: 10000; objects: .clickable;">

</a-camera>  

 

Em raycaster, especificamos que todos os objetos com a classe .clickable, serão clicáveis. Logo, para todos os ícones, devemos adicionar o seguinte atributo class=”clickable”.

Para permitir a interatividade, o raycaster gera uma linha a partir do local em que o usuário clicar até a cena. Dessa forma, se algum objeto interativo, ou seja, que possui a classe .cliclable, ficar no caminho da linha, o evento de click será disparado. 

Agora precisamos criar o script que adiciona os comportamentos decorrentes do click nos botões. Para isso, vamos importar o arquivo index.js no head do index.html da seguinte forma:

<script defer src="./assets/scripts/index.js"></script>

 

O atributo defer impedirá que o script seja executado até que a página HTML esteja pronta.

No arquivo javascript, precisamos “escutar” os eventos de click para cada botão. Para selecionar os elementos, podemos utilizar o método document.querySelector(), especificando o id que corresponde a cada um dos objetos, conforme o código abaixo. 

const btnGithub = document.querySelector("#github-button");
const btnLinkedin = document.querySelector("#linkedin-button");
const btnTwitter = document.querySelector("#twitter-button");
const btnEmail = document.querySelector("#email-button");
const btnWebsite = document.querySelector("#web-button");

 

Após selecionarmos os elementos, podemos inserir os eventos de click usando o método addEventListener(). No método precisamos implementar a função que será executada quando este evento for disparado. Na nossa aplicação, cada um dos botões abrirá uma página web específica em uma nova janela ou tab. Coloque a URL de suas contas e páginas web.

btnGithub.addEventListener('click', () => {
    window.open('https://github.com/pitanglabs', '_blank');
});

btnLinkedin.addEventListener('click', () => {
    window.open('https://linkedin.com/in/', '_blank');
});

btnTwitter.addEventListener('click', () => {
    window.open('https://twitter.com/', '_blank');
});


btnEmail.addEventListener('click', () => {
    window.open('mailto:labs-l@pitang.com');
});

btnWebsite.addEventListener('click', () => {
    window.open('https://www.pitang.com/', '_blank');
});

 

Scanner Customizado

Para customizarmos a nossa aplicação, podemos inserir, opcionalmente, um scanner customizado conforme o exemplo disponibilizado pela biblioteca MindAR.

                                Figura 6: Scanner customizado do MindAR.

 

Para tal, coloque o código abaixo no body do seu index.html e na tag img, especifique o caminho para a imagem do cartão de visitas.

<div id="example-scanning-overlay" class="hidden">
    <div class="inner">
        <img src="./assets/target/businessCard.png" />
        <div class="scanline"></div>
    </div>
</div>

 

Em seguida, importe o arquivo index.css no head da seguinte forma:

<link rel="stylesheet" href="assets/styles/index.css" />

 

Precisamos agora, sobrescrever o scanner padrão do MindAR através do parâmetro uiScanning na propriedade mindar-image em a-scene, da seguinte forma: 

<a-scene
  mindar-image="imageTargetSrc: ./assets/target/target.mind; uiScanning: #example-scanning-overlay"
  color-space="sRGB"
  renderer="colorManagement: true, physicallyCorrectLights"
  vr-mode-ui="enabled: false"
  device-orientation-permission-ui="enabled: false">


...

 

 No seu index.css, coloque o código abaixo, em conformidade com essa demo.

body {
    margin: 0;
}

.container {
    /* ocupar toda a tela*/
    overflow: hidden;
    position: absolute;
    width: 100%;
    height: 100%;
}

/* Inicio do Scanning do mindar */
#example-scanning-overlay {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background: transparent;
    z-index: 2;
}

@media (min-aspect-ratio: 1/1) {
    #example-scanning-overlay .inner {
        width: 50vh;
        height: 50vh;
    }
}

@media (max-aspect-ratio: 1/1) {
    #example-scanning-overlay .inner {
        width: 80vw;
        height: 80vw;
    }
}

#example-scanning-overlay .inner {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;

    background: linear-gradient(to right, white 10px, transparent 10px) 0 0,
        linear-gradient(to right, white 10px, transparent 10px) 0 100%,
        linear-gradient(to left, white 10px, transparent 10px) 100% 0,
        linear-gradient(to left, white 10px, transparent 10px) 100% 100%,
        linear-gradient(to bottom, white 10px, transparent 10px) 0 0,
        linear-gradient(to bottom, white 10px, transparent 10px) 100% 0,
        linear-gradient(to top, white 10px, transparent 10px) 0 100%,
        linear-gradient(to top, white 10px, transparent 10px) 100% 100%;
    background-repeat: no-repeat;
    background-size: 40px 40px;
}

#example-scanning-overlay.hidden {
    display: none;
}

#example-scanning-overlay img {
    opacity: 0.6;
    width: 90%;
    align-self: center;
}

#example-scanning-overlay .inner .scanline {
    position: absolute;
    width: 100%;
    height: 10px;
    background: white;
    animation: move 2s linear infinite;
}

@keyframes move {

    0%,
    100% {
        top: 0%;
    }

    50% {
        top: calc(100% - 10px);
    }
}

/* Fim do Scanning do mindar */

Configuração de rastreamento

Se formos executar a aplicação, podemos observar em alguns momentos, tremores nos elementos. Este é considerado um problema comum em aplicações de RA, devido a alguns fatores como ruídos provenientes da câmera. 

                                       Figura 7: Elementos com tremores

 

Para solucionar este problema podemos ajustar os parâmetros filterMinCF e filterBeta. Informações técnicas podem ser consultadas na documentação oficial do MindAR. Mas, de modo geral, ao diminuir o valor de filterMinCF estamos reduzindo os tremores (jitter) e ao aumentar o valor de filterBeta, estamos reduzindo o delay. 

Os valores padrões de filterMinCF e filterBeta são 0.001 e 1000. Experimentalmente, alteramos esses valores no atributo mindar-image, com o objetivo de reduzir os tremores sem aumentar tanto o delay.

<a-scene
      mindar-image="imageTargetSrc: ./assets/target/target.mind; filterMinCF:0.001; filterBeta: 0.09; uiScanning: #example-scanning-overlay"
      color-space="sRGB"
      renderer="colorManagement: true, physicallyCorrectLights"
      vr-mode-ui="enabled: false"
      device-orientation-permission-ui="enabled: false">

...

 

Podemos observar através do gif a seguir, que os tremores foram reduzidos substancialmente, garantindo uma experiência de usuário mais adequada.

                            Figura 8: Elementos com redução dos tremores.

 

Ao final, seu projeto completo poderá estar semelhante aos códigos presentes nesse repositório

Deploy

Para finalizar o nosso tutorial, faremos o deploy na ferramenta Vercel, através dos seguintes passos:

  1. Crie um repositório no seu github para colocar o seu código;

  2. Faça o cadastro no Vercel, de preferência com a sua conta do Github;

  3. Crie um novo projeto no Vercel;

 

4. Importe a sua conta do Github 

5. Você pode dar acesso a todos os repositórios ou apenas ao que você acabou de criar;

 

6. Após instalar e selecionar o repositório, clique no botão Import;

7. Caso queira, altere o nome do projeto, em seguida, selecione a opção de deploy e aguarde.

8. Uma nova página será aberta, informando que o deploy foi realizado com sucesso.

9. Clique na janela em branco para abrir o site ou aperte no botão de Go to Dashboard para visualizar o status, domínios, etc.

10. No seu cartão de visitas, altere jane.com/card para a URL gerada pelo Vercel. Em seguida, refaça o procedimento de compilação do target com a imagem nova e substitua no seu projeto.

11. Por fim, realize o push no github e aguarde, que o Vercel irá alterar a página com as novas atualizações.