Maratona Behind the Code 2020: Faça parte do Desafio. Inscreva-se até 7 de Agosto.

Crie aplicativos móveis da web com HTML5 e seus novos recursos visuais de IU

O HTML5 é uma tecnologia popular desde seu lançamento e por um bom motivo. Ele trouxe recursos semelhantes aos de aplicativos de desktop para o navegador da web, não apenas no desktop, mas também nos dispositivos móveis.

Nesta série de cinco partes, analisaremos alguns dos recursos mais populares que fazem parte do HTML5. Em cada parte, também escrevemos um código para demonstrar esses recursos e observar como eles funcionam tanto nos navegadores de desktop quanto nos móveis.

O HTML5 vem com vários novos recursos para aplicativos da web móveis, incluindo os visuais, que geralmente causam o maior impacto. O Canvas é o recurso da nova IU que mais chama a atenção, fornecendo gráficos 2D completos no navegador. Neste artigo, você aprende a usar o Canvas e também alguns dos outros novos elementos visuais no HTML 5 que são mais sutis, mas fazem uma grande diferença para os usuários móveis.

Pré-requisitos

Neste tutorial, desenvolveremos um aplicativo da web para demonstrar os recursos visuais apresentados no HTML5. O código que veremos usa as principais tecnologias da web, como HTML, Cascading Style Sheets (CSS) e JavaScript. Para testar o aplicativo no desktop e em dispositivos móveis, recomendamos o uso das versões mais recentes dos navegadores da web.

Criando gráficos com o Canvas

O Canvas oferece uma API de desenho nativa para navegadores da web. Usando a API do Canvas, é possível desenhar diferentes formas, como linhas, círculos e polígonos, e preenchê-los com cores e gradientes. É possível criar textos e executar várias transformações geométricas. Ele pode ser usado para recursos, como visualização de dados, animação e foto e processamento de vídeo. A melhor coisa é que o Canvas tem um suporte abrangente nas versões recentes de quase todos os navegadores populares.

Veremos como criar um gráfico usando o Canvas. A Figura 1 mostra uma captura de tela do aplicativo: um gráfico de barras de resultados anuais.

Resultados anuais no gráfico de barras

O gráfico é gerado usando a API do Canvas. A listagem 1 mostra o código HTML usado para criar esse gráfico.

Listagem 1. HTML do gráfico de barras

<!DOCTYPE html>
<html>
  <head>
    <meta http‑equiv="Content‑Type" content="text/html; charset=UTF‑8" />
    <title>HTML 5 Reports</title>
    <script type="text/javascript">
      const initialize = () => {
        const data = [
          { year: "2007", sales: 49 },
          { year: "2008", sales: 131 },
          { year: "2009", sales: 294 },
          { year: "2010", sales: 405 }
        ];
        const report = { x: "year", y: "sales", data };
        generateGraph(report, 350, 300);
      };

   </script>
  </head>
  <body onload="initialize()">
    <canvas id="graph"></canvas>
  </body>
</html>

O corpo do documento contém um elemento do Canvas. Quando a página é carregada, a função initialize() é chamada. Essa função passa os dados estáticos do relatório para a função generateGraph, que é aquela que gera o gráfico de barras, como mostra a Listagem 2.

Listagem 2. A função generateGraph

const generateGraph = (report, maxWidth, maxHeight) => {
        const { data } = report;
        const canvas = document.getElementById("graph");
        const axisBuffer = 20;
        canvas.height = maxHeight + 100;
        canvas.width = maxWidth;
        const context = canvas.getContext("2d");

        const width = 50;
        const buffer = 20;
        const i = 0;
        let x = buffer + axisBuffer;
        context.font = "bold 12px sans‑serif";
        context.textAlign = "start";

        data.forEach(item => {
          context.fillStyle = "rgba(0, 0, 200, 0.9)";
          context.fillRect(
            x,
            maxHeight - item[report.y] / 2,
            width,
            item[report.y] / 2
          );
          context.fillStyle = "rgba(0, 0, 0, 0.9)";
          context.fillText(item[report.x], x + width / 4, maxHeight + 15);
          x += width + buffer;
        });

        // draw the horizontal axis
        context.moveTo(axisBuffer, maxHeight);
        context.lineTo(axisBuffer + maxWidth, maxHeight);
        context.strokeStyle = "black";
        context.stroke();

        // draw the vertical axis
        context.moveTo(axisBuffer, 0);
        context.lineTo(axisBuffer, maxHeight);
        context.stroke();

        // draw gridlines
        const lineSpacing = 50;
        const numLines = maxHeight / lineSpacing;
        let y = lineSpacing;
        context.font = "10px sans‑serif";
        context.textBaseline = "middle";

        for (let i = 0; i < numLines; i++) {
          context.strokeStyle = "rgba(0,0,0,0.25)";
          context.moveTo(axisBuffer, y);
          context.lineTo(axisBuffer + maxWidth, y);
          context.stroke();
          context.fillStyle = "rgba(0,0,0, 0.75)";
          context.fillText("" + 2 * (maxHeight - y), 0, y);
          y += lineSpacing;
        }
      };

Na função generateGraph, primeiro você configura os objetos necessários para criar o relatório, como as variáveis de largura e altura da tela e de preenchimento. Você também cria o objeto de contexto do Canvas, que será usado para o desenho real. Em seguida, você desenha os gráficos de barras na Figura 1 iterando sobre os dados do relatório. Você configura a propriedade fillStyle usando a notação rgba para definir a cor e o valor alfabético (a transparência da cor será discutida em uma próxima seção). Depois de configurar a propriedade fillStyle, crie o gráfico de barras para o ponto de dados usando a API fillRect. Aqui, especificamos o ponto de partida (x,y) do retângulo e sua altura e largura. Em seguida, redefinimos o fillStyle para imprimir algum texto como parte do relatório. Use a API fillText para desenhar o texto na tela. Essa API usa o ponto de partida (x,y) e o texto. Em seguida, faça isso para cada um dos pontos de dados, criando um gráfico de barras com um rótulo abaixo dele.

Depois, desenhe os eixos horizontal e vertical. Para cada um deles, use a API moveTo para configurar o ponto a partir do qual você começará a desenhar uma linha. Em seguida, use a API lineTo para desenhar uma linha a partir do ponto de partida até o ponto de término passado para a chamada lineTo e chame a API stroke para desenhar uma linha. Depois, desenhe as linhas de grade juntamente com seus rótulos. Desenhe linhas com espaçamento igual usando a mesma combinação de moveTo, lineTo e stroke.

Neste exemplo, discutimos algumas das APIs mais usadas do Canvas. Há várias outras funções que fazem parte da API do Canvas que permitem que você faça coisas incríveis.

O mundo maravilhoso do CSS

Ao falar sobre HTML5, é possível pensar instantaneamente nas identificações HTML e em muitas novas tags introduzidas como parte da especificação, mas a identificação HTML é apenas uma parte da história. O JavaScript e o CSS são partes igualmente importantes para o desenvolvimento da web. Muitos novos elementos de interface com o usuário foram apresentados como parte do CSS 3.0. Na Figura 2, veja uma página da web usando alguns dos recursos do CSS 3.0.

Recursos do CSS

Vamos analisar o código (na Listagem 3) que gerou essa página da web.

Listagem 3. Código para demonstrar os novos recursos do CSS

<!DOCTYPE html>
<html>
   <head>
      <script type="text/javascript">

function init() {
  var i = 0;
  var row = {};
  var cell = {};
  var topics = [
    "nth-child",
    "gradients",
    "alpha",
    "text effects",
    "reflections",
    "transformations"
  ];
  for (i = 0; i < topics.length; i++) {
    row = document.createElement("tr");
    cell = document.createElement("td");
    cell.appendChild(document.createTextNode(topics[i]));
    row.appendChild(cell);
    document.getElementById("dtable").appendChild(row);
  }
}

      </script>
      <style type="text/css">
         header > h1{
         color: yellow;
         background: linear-gradient(to right, red , yellow);
         }
         table tr:nth-child(odd) {
         color: navy;
         }
         table tr:nth-child(even) {
         color: green;
         }
         input[type="text"]{
         background: rgba(150, 30, 30, 0.5);
         }
      </style>
   </head>
   <body onload="init()">
      <header>
         <h1>The World of CSS3</h1>
      </header>
      <table id="dtable"></table>
      <div id="formSection">
         <label for="name">What's your name?</label>
         <input type="text" id="name"></input>
         <button id="rtBtn" onclick="rotate()">Rotate</button>
      </div>
   </body>
</html>

Dentro do corpo da página, a primeira coisa a observar é a identificação de cabeçalho, um novo elemento HTML introduzido no HTML5. Esse elemento pode ser usado para definir um cabeçalho de uma página ou uma seção.

Se você observar o elemento de estilo no código acima, estamos usando o seletor do CSS header > h1 para definir o estilo do texto de cabeçalho. Isso deixará o texto amarelo e o plano de fundo com um gradiente linear do vermelho para o amarelo. Embora esses estilos funcionem bem com a versão mais recente da maioria dos navegadores, alguns navegadores, principalmente as versões mais antigas, podem exigir um prefixo específico do navegador para que alguns desses estilos funcionem corretamente. Após o cabeçalho, temos uma tabela com o ID dtable. Use o seletor css nth-child. Aqui, o CSS exibe as linhas ímpares da tabela em azul-marinho e as linhas pares em verde. Antes isso exigia um código JavaScript customizado, mas agora isso pode ser feito facilmente com os seletores do CSS.

O último elemento visual na página é o campo de texto vermelho com o rótulo What’s your name? e um botão Rotate. Aqui foi possível usar um seletor direcionando um atributo específico do elemento. O seletor input[type="text"] aplica-se somente a elementos de entrada do tipo texto.

Vamos observar o código na Listagem 4 para saber o que o botão Rotate faz.

Listagem 4. Função de rotação do JavaScript usando CSS

function rotate() {
    document.getElementById("formSection").style["transform"] = "rotateZ(-5deg)";
    document.getElementById("formSection").style["transition"] =
        "transform 2s ease‑in‑out";
    document.getElementById("rtBtn").innerHTML = "Undo";
    document.getElementById("rtBtn").onclick = function() {
        document.getElementById("formSection").style["transform"] = "";
        document.getElementById("rtBtn").innerHTML = "Rotate";
        document.getElementById("rtBtn").setAttribute("onclick", "rotate()");
    };
}

O botão chama function rotate quando clicado. Essa função usa JavaScript para mudar o CSS que está aplicado à div formSection. Quando clicado, o botão gira a div em cinco graus no sentido anti-horário. Isso é feito usando o estilo de transformação com o valor rotateZ(-5deg). Também configuramos o estilo de transformação para transform 2s ease-in-out para que a rotação demore dois segundos, começando lentamente, acelerando e, em seguida, desacelerando novamente. Na Figura 3, veja os campos rotacionados com um botão para desfazer a rotação.

Campos rotacionados

Agora vamos observar alguns dos efeitos interessantes de layout, imagem e texto apresentados no CSS na Figura 4. O código para isso está na Listagem 5.

Layout

Listagem 5. Código para demonstrar os novos recursos do CSS

<!DOCTYPE html>
<html>

<head>
    <style type="text/css">
        h2 {
            -webkit-text-fill-color: blue;
            -webkit-text-stroke-color: yellow;
            -webkit-text-stroke-width: 1.5px;
            background: -webkit-gradient( radial, 430 50, 0, 430 50, 200, from(red), to(#000));
            -webkit-box-reflect: below 5px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.5, transparent), to(white));
        }

        h3 {
            color: rgba(0, 0, 255, 0.75);
            background: rgba(255, 255, 0, 0.5);
        }

        .xyz {
            text-shadow: #6374ab 4px -4px 2px;
            white-space: nowrap;
            width: 14em;
            height: 2em;
            overflow: hidden;
            text-overflow: ellipsis;
            border: 1px solid #bbb;
            border-radius: 9px;
            background-color: #fff;
        }

        .abc {
            border: 1px solid #000;
            border-radius: 9px;
            column-count: 4;
            column-rule: 1px solid #a00;
            column-gap: 0.75em;
        }
    </style>
</head>

<body onload="init()">
    <h2>The Gettysburg Address</h2>
    <h3>Abraham Lincoln, Gettysburg, PA. November 19, 1863</h3>
    <div class="xyz">
        Há muitos anos, nossos pais criaram neste continente uma nova nação, concebida na liberdade e dedicada à afirmação de que todos os homens são criados iguais.
    </div>
    <div class="abc">
        Agora estamos engajados em uma grande guerra civil, testando se essa nação, ou se qualquer nação concebida e dedicada da mesma forma, consegue resistir por muito tempo. Nos encontramos em um grande campo de batalha dessa guerra. Acabamos por dedicar uma parte desse campo, como um local de descaso final àqueles que aqui deram suas vidas e onde a nação pode sobreviver. É completamente adequado que façamos isso.
    </div>
</body>

</html>

Vamos percorrer elemento por elemento nesse código. Primeiro, temos o título “The Gettysburg Address” com os seguintes estilos:

  1. Usamos os estilos -webkit-text-fill-color, -webkit-text-stroke-color e -webkit-text-stroke-width para criar o efeito azul dentro do amarelo.
  2. Um plano de fundo vermelho e preto foi colocado atrás do texto configurando o estilo de plano de fundo -webkit-gradient. No exemplo anterior, usamos um gradiente linear, mas aqui estamos usando um gradiente radial.
  3. Finalmente, aplicamos um reflexo ao título configurando o estilo -webkit-box-reflect. Ele foi configurado para refletir os cinco pixels do cabeçalho abaixo dele, com um efeito de gradiente aplicado ao reflexo, fazendo parecer que o reflexo está esmaecendo.

Para o próximo cabeçalho, aplicamos um estilo simples, com cor de texto e de plano de fundo. Usamos a função rgba para especificar os valores vermelho, verde e azul e um valor de transparência alfa. O valor de transparência alfa 0.0 é transparente e o valor 1.0 é completamente opaco.

Em seguida, temos um parágrafo com uma borda ao redor do texto. Os cantos arredondados da borda são feitoso estilo border-radius. Também aplicamos uma sombra ao texto usando o estilo text-shadow. Finalmente, como é possível observar, o texto está muito longo para a altura e a largura configuradas para a div pai. Configurando o estilo text-overflow, podemos usar reticências (…), para que o texto não fique truncado.

Finalmente, é possível observar como o último parágrafo é exibido como quatro colunas, o que é feito usando o estilo column-count. Cada coluna também tem um separador de colunas que usa o estilo column-rule.

Juntamente com os recursos discutidos, há vários outros recursos apresentados no CSS 3.0 para ajudar a atingir efeitos visuais incríveis, que funcionam em diferentes navegadores, sem a necessidade de escrever um código customizado complicado.

Nova semântica

Muitos novos elementos foram incluídos na especificação HTML5. Embora alguns deles sejam elementos visuais, outros incluem um significado semântico adicional sem nenhuma mudança na aparência. Essas novas semânticas são importantes para deixar os aplicativos da web acessíveis para usuários não visuais, incluindo os que usam tecnologias assistivas, como leitores de tela, e até mesmo programas como os crawlers de mecanismo de procura.

A Figura 5 mostra uma página da web que usa alguns dos novos elementos semânticos.

Novos elementos semânticos

Esse exemplo tem um elemento de cabeçalho, um elemento nav, um artigo, uma seção e um elemento à parte. Esses elementos não causam nenhuma renderização especial. Eles apenas incluem um valor semântico e podem ser usados para escrever o CSS que fornece tratamentos visuais para corresponder a esse valor semântico. O código da página mostrada na Figura 4 está na Listagem 6.

Listagem 6. Novos elementos semânticos no HTML5

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Get the latest markup</title>
</head>

<body>
    <header style="border: 1px dotted #000;border-radius: 3px;">
        <hgroup align="center">
            <h1>Real documents have headers</h1>
            <h2>Even if they don't say so</h2>
        </hgroup>
        <hgroup>
            <nav style="column-count:3; column-rule: 1px solid #a00;">
                <a href="new-css.html">CSS3</a>
                <br />
                <a href="report.html">Canvas</a>
                <br />
                <a href="elements.html">Markup</a>
            </nav>
        </hgroup>
    </header>
    <article>
        <h1>There are a lot of new markup elements in HTML5</h1>
        <time datetime="2010-05-16" pubdate>Sunday, May 16</time>
        <section>
            Did you notice that we just had two H1's? But it's cool!
        </section>
        <aside style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
            If this page was really popular, I'd put an ad here and make some serious cash
        </aside>
    </article>
</body>

</html>

No código acima, usamos vários dos elementos novos já mencionados. Aplicamos estilos CSS para criar uma caixa com cantos arredondados em torno de um cabeçalho e para criar separadores para o elemento nav. Também usamos o estilo de estouro de texto no elemento à parte. Usando os elementos semânticos do HTML5 com o CSS 3.0, não apenas criamos um markup muito mais significativo, como também definimos o estilo dele sem grandes esforços.

Agora, vamos observar na Figura 6 os elementos visuais apresentados no HTML5.

Elementos visuais

A tela na Figura 6 usa vários dos novos elementos de formulário disponíveis no HTML5. Embora esses elementos possam ser semelhantes aos existentes, eles oferecem uma representação visual e uma experiência do usuário melhores com base no dispositivo e no navegador do usuário.

Vamos observar a página da web acima no navegador Safari do iPhone, na Figura 7.

Navegador do iPhone

como é possível observar, o campo de data que parecia um campo de formulário normal é renderizado de maneira diferente em um iPhone, fornecendo uma experiência melhor ao usuário. O código usado para gerar o formulário é mostrado na Listagem 7.

Listagem 7. Elementos do formulário HTML5 no código

<form id="settings">
    <fieldset id="inputs" style="border: 1px solid #000;border-radius: 6px;">
        <legend>Settings</legend>
        <label for="name">Username</label>
        <input id="name" name="name" type="text" required autofocus />
        <br />
        <label for="name">Name</label>
        <input id="name" name="name" type="text" placeholder="First and last name" required />
        <br />
        <label for="email">Email</label>
        <input id="email" name="email" type="email" placeholder="example@domain.com" required />
        <br />
        <label for="phone">Phone</label>
        <input id="phone" name="phone" type="tel" placeholder="Eg. +447500000000" required />
        <br />
        <label for="dob">Date of birth</label>
        <input id="dob" name="dob" type="date" required />
        <fieldset style="border: 1px dotted #000; border-radius: 6px">
            <legend>Preferred Contact Method</legend>
            <ol>
                <li>
                    <input id="emailMeth" name="contactMethod" type="radio" />
                    <label for="emailMeth">Email</label>
                </li>
                <li>
                    <input id="phoneMeth" name="contactMethod" type="radio" />
                    <label for="phoneMeth">Phone</label>
                </li>
            </ol>
        </fieldset>
        <label for="climate">Preferred external temperature</label>
        <input id="climate" name="climate" type="range" min="50" max="100" step="5" value="70" />
        <br />
        <label for="color">Favorite color</label>
        <input id="color" name="color" type="color" />
        <br />
        <label for="referrer">Where'd you hear about us?</label>
        <input type="url" name="refUrl" id="referrer" list="urls" />
        <datalist id="urls">
            <option label="TechCrunch" value="http://www.techcrunch.com/"> </option>
            <option label="ReadWrite Web" value="http://www.readwriteweb.com/">
            </option>
            <option label="Engadget" value="http://www.engadget.com/"> </option>
            <option label="Ajaxian" value="http://www.ajaxian.com/">
            </option>
        </datalist>
        <br />
        <button type="button" onclick="checkInputs()">Save</button>
    </fieldset>
</form>

Usamos vários novos recursos do HTML5 na Listagem 7. Usamos o atributo necessário para marcar um campo como obrigatório, que também pode ser usado durante a validação do formulário. Também usamos o atributo autofocus que permite focar um campo automaticamente quando a página é carregada.

Para muitos dos elementos do formulário, usamos o atributo de item temporário para fornecer uma sugestão que descreve o elemento. Também usamos novos tipos de campos de entrada como e-mail, telefone, data, intervalo, cor e URL. Os campos de entrada com esses novos tipos podem parecer os mesmos, mas eles oferecem experiências diferentes aos usuários com base nos dispositivos e navegadores usados. Por exemplo, observamos como o campo de entrada de tipo de data é exibido no iPhone na Figura 7.

Resumo

Neste tutorial, abordamos vários dos recursos visuais do HTML5, incluindo o Canvas, os recursos do CSS 3.0 e os novos elementos semânticos e visuais do HTML. Usando esses recursos, é possível criar aplicativos da web com interfaces com o usuário e experiências incríveis para diferentes navegadores, sem a necessidade de escrever um código customizado complicado. Usando esses elementos visuais juntamente com os outros recursos discutidos nas partes anteriores desta série, é possível criar aplicativos da web no mesmo nível dos aplicativos nativos.

Agradecimentos

Este artigo foi escrito originalmente por Michael Galpin e publicado em 29 de junho de 2010.