Estudo de caso: MathBoard em HTML5

Introdução

Aplicativo MathBoard

O MathBoard no iPad, um aplicativo do PalaSoftware, é 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 para HTML5.

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

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

Requisitos

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

  1. Porta de alta fidelidade da aparência e interface do usuário do aplicativo original para iPad.
  2. Adapte ao formato desejado (por exemplo, PC/Mac com teclado/mouse vs. tela touch).
  3. Implementar 100% dos recursos aplicáveis.
  4. Segmentar principalmente navegadores HTML5.
  5. Tornar o aplicativo "sem servidor" para que ele seja executado inteiramente no cliente e possa ser hospedado em um servidor estático ou aplicativo empacotado do Google Chrome.
  6. Crie uma versão 1.0 com todos os recursos, mas o solucionador de problemas em menos de um mês.

Arquitetura

Arquitetura

Dados os requisitos, decidimos ficar com a seguinte arquitetura:

  1. HTML5: como não temos nenhum requisito de suporte a HTML4, decidimos usar HTML5 como base.
  2. jQuery: Embora o HTML5 tenha muitos seletores avançados que tornam o jQuery tão incrível, decidimos continuar com o jQuery, pois ele nos ofereceu uma maneira muito robusta e madura de manipular o DOM e eventos relacionados. O jQuery também tem o benefício de ser mais centrado 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 fornece uma excelente API e prática recomendada para trabalhar com o DOM. No entanto, para o aplicativo MathBoard HTML5, precisávamos de uma estrutura de estilo MVC ou MVP para orquestrar todas as diferentes visualizações. O SnowUI é uma estrutura MVC simples, porém avançada, baseada no jQuery. Ele oferece um mecanismo MVC centrado no DOM e uma maneira flexível de criar componentes personalizados, além de permitir que o desenvolvedor de aplicativos use qualquer biblioteca de widgets/controles ou código personalizado que considere ideal.

Considerações do iPad para o PC

Ao transferir o aplicativo para HTML5 para uso em PCs, 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 é exclusivamente vertical, o que não é ideal para telas de PC, já que geralmente são usadas na horizontal. Consequentemente, 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 para Web é a interface de entrada. No iPad, você tem apenas a interface de toque. No PC, é preciso considerar o mouse e o teclado.

Os controles de entrada do MathBoard no iPad são altamente sofisticados. Queríamos a mesma representação de alta fidelidade na interface da Web. A solução foi adicionar suporte a atalhos de teclado e replicar controles de interface usando o posicionamento de CSS. A porta para HTML5 era perfeita como um pixel:

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

Assim como na interface do iPad, permitimos que o usuário clique na seta para a esquerda e para a direita para alterar 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 mover de um campo de entrada para outro, e as setas ← e → percorrem os valores.

Um recurso da versão do iPad que não fazia muito sentido para a interface do PC era a prancheta. Embora pudesse ser complicado implementar esse método, 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 HTML5

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

Armazenamento local

O MathBoard permite que os usuários salvem o teste para reproduzi-lo mais tarde. O HTML5 MathBoard implementa esse recurso usando localStorage do HTML5, usando a interface DAO do SnowUI.

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 e JSON.stringify como texto.

O DAO da snowUI é um wrapper de interface CRUD simples que permite que a interface busque dados sem precisar se preocupar com a forma como eles são realmente armazenados. A implementação do DAO cuida das especificações do 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 são armazenados como strings JSON em localStorage.

Por exemplo, o DAO do valor da configuração tinha a seguinte 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 é registrado para o settingValue, a interface pode fazer a seguinte chamada sem precisar se preocupar com a lógica do armazenamento:

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 do tipo real "Chalkduster" em nosso aplicativo:

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

E, como essa fonte era o padrão para quase todo o texto no aplicativo, também a tornamos padrão para o corpo.

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

CSS3 gradiente, sombra, cantos arredondados

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

Também usamos propriedades CSS3 avançadas 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 MathBoard HTML5, replicamos todas as animações do iPad e adicionamos uma nova para o painel deslizante da direita. Graças às transições CSS3, adicionar animações era trivial e permitiu o melhor desempenho.

Tínhamos três animações principais nos aplicativos.

1) O painel deslizante para a direita

A primeira animação está no painel direito (#rightPane), que é fechado quando o usuário inicia um novo teste e quando ele termina. Para criar esse efeito, usamos a transição CSS a seguir e a acionamos via JavaScript. O estilo padrão do rightPane é 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);

Confira algumas observações sobre essa implementação:

  1. Como os tamanhos dos aplicativos são fixos, poderíamos ter usado uma classe CSS ".close" e fixado no código a posição fechada da mesma forma que fixamos o código aberto.
  2. Também poderíamos ter usado CSS "translate", que teria um desempenho melhor do que animar a propriedade "left" do painel. Isso vale principalmente 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 nesse caso, porque a posição original foi definida antes da modificação. No entanto, ela permite que o navegador torne a animação mais suave exibindo o teste pouco antes de deslizar o painel rightPane para dentro.

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 é exibida na parte de baixo da tela e rola até a seção adequada.

Para isso, fizemos uma transição semelhante para o 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 interface da caixa de diálogo em cache, acabamos exibindo-a uma vez e rolando até ela. Inicialmente, tentamos com display: none. Essa abordagem estava errada porque o navegador presumiu que a caixa de diálogo não precisa ser mostrada. A solução era mostrar as configurações com um z-index: -1 na inicialização, tornando-o invisível ao usuário, mas visível ao navegador.

3) Animação do teste concluído ou da mensagem incorreta

A terceira animação é, na verdade, duas em uma. Quando a mensagem de "sucesso" ou "incorreto" aparecer, primeiro dimensione até um ponto, aguarde um pouco e, por fim, aumente ainda mais e desapareça. Para isso, temos dois estilos de animação CSS3 e orquestramos isso via 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 era usar a tag de áudio e chamar play() neles. Estes 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 viabilizando uma nova safra de aplicativos da Web, para computadores e para dispositivos móveis. O CSS3 foi fundamental na personalização da aparência do aplicativo para corresponder à alta sofisticação do MathBoard para iPad. O armazenamento em HTML5 era perfeitamente adequada para a persistência de dados, e a simplicidade do áudio HTML5 nos permitiu replicar o aplicativo para iPad.