Estudo de caso: HTML5 MathBoard

Introdução

Aplicativo MathBoard

O MathBoard no iPad, um aplicativo da PalaSoftware, é um aplicativo altamente refinado com muitas animações sutis, mas naturais, e uma aparência realista única. O objetivo era fazer a porta de maior fidelidade do aplicativo para iPad em HTML5.

A N2N-Apps é uma empresa de desenvolvimento de software focada na criação de aplicativos da Web e para dispositivos móveis de última geração com tecnologia HTML5. A empresa foi fundada em 2010 por Jeremy Chone, que, após 11 anos de experiência em engenharia e gestão na Netscape, Oracle e Adobe, decidiu compartilhar sua experiência com empresas para criar aplicativos da Web e para dispositivos móveis de alta qualidade. O N2N-Apps se concentra na qualidade e na velocidade de entrega.

Fazer o download do MathBoard na Chrome Web Store Fazer o download do MathBoard na Chrome Web Store (versão sem custo financeiro)

Requisitos

Os principais requisitos para esse projeto de portabilidade para HTML5 foram os seguintes:

  1. Porta de alta fidelidade da aparência e da interface do usuário do aplicativo original do iPad.
  2. Adaptar ao formato de destino (ou seja, PC/Mac com teclado/mouse versus tela touch).
  3. Implemente 100% dos recursos aplicáveis.
  4. Segmente principalmente navegadores HTML5.
  5. Faça o aplicativo funcionar sem servidor, para que ele seja executado inteiramente no cliente e possa ser hospedado em um servidor estático ou em um aplicativo empacotado do Google Chrome.
  6. Crie uma versão 1.0 com todos os recursos, exceto a solução de problemas, em menos de um mês.

Arquitetura

Arquitetura

Com base nos requisitos, decidimos usar a seguinte arquitetura:

  1. HTML5: como não temos requisitos de suporte ao HTML4, decidimos usar o HTML5 como base.
  2. jQuery: embora o HTML5 tenha muitos dos seletores avançados que tornam o jQuery tão ótimo, decidimos continuar com o jQuery porque ele oferece uma maneira muito robusta e amadurecida de manipular o DOM e os eventos relacionados. O jQuery também tem o benefício de ser mais focado no DOM, o que tende a tornar o design e a implementação de um aplicativo mais próximos do HTML.
  3. SnowUI: o jQuery oferece uma ótima API e práticas recomendadas para trabalhar com o DOM. No entanto, para o aplicativo MathBoard HTML5, precisamos de um framework de estilo MVC ou MVP para orquestrar todas as diferentes visualizações. O SnowUI é um framework MVC simples, mas poderoso, em cima do jQuery. Ele fornece um DOM mecanismo MVC centrado e uma maneira flexível de construir componentes personalizados enquanto deixando a oportunidade para o desenvolvedor do aplicativo usar qualquer widget/controle biblioteca ou código personalizado que ele ou ela considera ideal.

Considerações sobre o iPad para PC

Ao portar o aplicativo para HTML5 para uso em PC, tivemos que fazer várias modificações no design e na interação do usuário com o aplicativo.

Orientação da tela

O iPad MathBoard é orientado exclusivamente na vertical, o que não era ideal para telas de PC, que geralmente são usadas na horizontal. Por isso, reorganizamos o design da interface e movemos o painel de configurações para o lado direito, em uma visualização deslizante (animada por transições CSS3).

Orientação da tela
Orientação da tela do iPad x HTML5

Entrada: teclado/mouse x toque

Outra diferença importante entre a versão para iPad e a versão da Web é a interface de entrada. No iPad, você tem apenas a interface de toque. No PC, é necessário considerar o mouse e o teclado.

Os controles de entrada do MathBoard no iPad são muito bem elaborados. Queríamos a mesma representação de alta fidelidade na interface da Web. A solução adicionou suporte a atalhos de teclado e replicação de controles de interface usando a posição do CSS. A porta para HTML5 foi perfeita:

Controles de interface
Configurações da versão do iPad e do HTML5

Como na interface do iPad, permitimos que o usuário clique nas setas para a esquerda e para a direita para mudar o valor de um controle. A linha vertical também pode ser arrastada para mudar rapidamente os valores. Um comportamento de repetição foi implementado para click e keydown para que os usuários possam acelerar a mudança de valor quando o mouse ou o teclado for pressionado.

O suporte a TAB foi adicionado para passar de um campo de entrada para outro, e as setas ← e → alternam entre os valores.

Um recurso da versão do iPad que não fazia muito sentido para a interface de PC era a mesa de desenho. Embora pudesse ser interessante implementar isso, desenhar números com um mouse não é muito prático. Em vez disso, decidimos passar mais tempo aprimorando a interface do teclado do que implementando a prancheta.

Recursos do HTML5

Na versão da Web do MathBoard, usamos muitos recursos do HTML5:

Armazenamento local

O MathBoard permite que os usuários salvem os testes para reproduzir mais tarde. O HTML5 MathBoard implementa esse recurso usando o localStorage HTML5 usando a interface SnowUI DAO.

localStorage foi uma escolha natural, já que os dados eram simples o suficiente e não exigiam indexação avançada. Armazenamos todos os testes em um formato JSON que JSON.stringify como texto.

O DAO snowUI é um wrapper de interface CRUD simples que permite que a interface busque dados sem se preocupar com a forma como eles são armazenados. A implementação do DAO cuida dos detalhes de armazenamento.

No MathBoard, os requisitos de armazenamento eram muito simples. Precisávamos armazenar apenas as configurações do usuário e os dados do teste. Ambos foram armazenados como strings JSON em localStorage.

Por exemplo, o DAO para o valor de configuração tinha esta aparência:

snow.dm.registerDao('settingValue', (function() {

  var _settingValues = null;

  function SettingValueDao() {};

  // ------ DAO CRUD Interface ------ //
  // get
  SettingValueDao.prototype.get = function(objectType, id) {
    return $.extend({},getSettingValues()[id]);
  };

  // find, remove

  // save
  SettingValueDao.prototype.save = function(objectType, data) {
    var storeValue = getSettingValues('settingValue')[data.id];
    if (!storeValue) {
      storeValue = {};
      getSettingValues()[data.id] = storeValue;
    }

    $.extend(storeValue, data);
    saveSettingValues();
  };
  // ------ /DAO CRUD Interface ------ //

  function getSettingValues() {
    if (_settingValues == null) {
      var settingValuesString = localStorage.getItem('settingValues');
      if (settingValuesString) {
        _settingValues = JSON.parse(settingValuesString);
      } else{
        _settingValues = {};
      }
    }

    return _settingValues;
  }

  function saveSettingValues(){
    var settingValues = getSettingValues();
    if (settingValues != null) {
      localStorage.removeItem('settingValues');
      localStorage.setItem('settingValues', JSON.stringify(settingValues)); 
    }
  }

  return new SettingValueDao();
})());

Depois que esse DAO for registrado para o settingValue, a interface poderá fazer a seguinte chamada sem precisar se preocupar com a lógica da loja:

var addition = snow.dm.get('settingValue', 'operator_addition');
addition.value = true; // to check the addition checkbox
snow.dm.save('settingValue', addition);

Fontes CSS3

O MathBoard usa fontes personalizadas. Graças ao suporte a fontes CSS3, foi fácil incluir a fonte "Chalkduster" no nosso aplicativo:

@font-face {
  font-family: Chalkduster;
  src: url(Chalkduster.ttf);
}

Como essa fonte era o padrão para quase todo o texto no app, a definimos como padrão para o corpo.

body {
  background: #333333;
  font-family: Chalkduster;
  color: #ffffff;
}

Gradiente, sombra e cantos arredondados do CSS3

Todos os gradientes, sombras, transparências e cantos arredondados são feitos com CSS3. Isso foi uma grande ajuda em comparação com a maneira tradicional de criar interfaces do usuário com .png.

Também usamos propriedades avançadas do CSS3 para personalizar a aparência da barra de rolagem e torná-la mais sutil. Consulte http://webkit.org/blog/363/styling-scrollbars/ para estilizar barras de rolagem em navegadores WebKit.

Transições CSS3

Para o HTML5 MathBoard, replicamos todas as animações do iPad e até adicionamos uma nova para o painel deslizante à direita. Graças às transições CSS3, adicionar animações foi trivial e permitiu o melhor desempenho.

Tivemos três animações principais nos aplicativos.

1.) Painel direito deslizante

A primeira animação está no painel direito (#rightPane), que desliza fechada quando o usuário inicia um novo teste e desliza aberta quando o usuário termina um teste. Para criar esse efeito, usamos a transição CSS a seguir e acionamos por JavaScript. O estilo padrão do rightPane está aberto:

#rightPane {
  /* look and feel, and layout property */
  position: absolute;
  width: 370px;
  height: 598px;
  top: 28px;
  left: 720px; /* open */
  -webkit-transition: all .6s ease-in-out;
}

Quando o usuário inicia um teste, nossa lógica JavaScript move o painel:

var $rightPane = $('#rightPane');
var left = $rightPane.position().left - 400;
setTimeout(function() {
  $rightPane.css('left', left + 'px');
}, 0);

Algumas observações sobre essa implementação:

  1. Como os tamanhos do aplicativo são fixos, poderíamos ter usado uma classe CSS '.close' e fixado a posição de fechamento da mesma forma que fixamos a posição de abertura.
  2. Também poderíamos usar o CSS "translate", que teria um desempenho melhor do que animar a propriedade "left" do painel. Isso é especialmente verdadeiro para dispositivos móveis (como iOS), em que as transformações 3D são aceleradas por hardware.
  3. O setTimeout não é estritamente necessário neste caso, já que a posição original foi definida antes da modificação. No entanto, ele permite que o navegador torne a animação mais suave mostrando o teste logo antes de deslizar o painel direito.

2.) Animação da caixa de diálogo de configurações

Quando o usuário clica em uma configuração à direita, a caixa de diálogo de configurações aparece na parte de baixo da tela e rola para baixo até a seção apropriada.

Para isso, fizemos uma transição semelhante ao painel direito. A única coisa que levou algum tempo foi resolver a instabilidade na primeira aparição da caixa de diálogo. Para instruir o navegador a armazenar a IU da caixa de diálogo em cache, acabamos exibindo-a uma vez e rolando até ela. No início, tentamos com display: none. Essa abordagem estava errada porque o navegador presumiu que a caixa de diálogo não precisava ser mostrada. A solução foi mostrar as configurações com um z-index: -1 na inicialização, tornando-o invisível para o usuário, mas visível para o navegador.

3.) Animação de mensagem de sucesso ou incorreta do teste

A terceira animação é na verdade duas em uma. Quando a mensagem "success" ou "incorrect" aparecer, primeiro aumente até um ponto, aguarde um pouco e, finalmente, aumente ainda mais e desapareça. Para isso, temos dois estilos de animação CSS3, e os orquestramos usando JavaScript em um evento webkitTransitionEnd.

.quiz-result > div.anim1 {
  opacity: 0.8;
  -webkit-transform: scale(6,6);
}
.quiz-result > div.anim2{
  opacity: 0;
  -webkit-transform: scale(9,9);
}
setTimeout(function() {
  $msg.addClass("anim1");
  $msg.bind("webkitTransitionEnd", function(){
    if ($msg.hasClass("anim1")) {
      setTimeout(function() {
        $msg.removeClass("anim1");
        $msg.addClass("anim2");
      }, 300);
    } else {
      $msg.remove();
      displayNextItem();
      freezeInput = false;
    }
  });
}, 0);

Tag de áudio

Quando os usuários respondem a um teste, o aplicativo emite um som de sucesso ou falha. A escolha simples foi usar a tag de áudio e chamar play(). Esses bits de áudio são adicionados à página principal do aplicativo:

<audio id="audioCorrect" src="correct.mp3" preload="auto" autobuffer></audio>
<audio id="audioWrong" src="wrong.mp3" preload="auto" autobuffer></audio>

Conclusão

O HTML5 está realmente permitindo uma nova geração de aplicativos da Web, para computadores e dispositivos móveis. O CSS3 foi fundamental para personalizar a aparência do aplicativo para corresponder à alta sofisticação do MathBoard para iPad. O armazenamento em HTML5 foi perfeito para a persistência de dados, e a simplicidade do áudio em HTML5 nos permitiu replicar o app para iPad.