Studium przypadku – HTML5 MathBoard

Wstęp

Aplikacja MathBoard

MathBoard na iPadzie, PalaSoftware, to bardzo dopracowana aplikacja z wieloma subtelnymi, ale naturalnymi animacjami oraz niepowtarzalnym realistycznym wyglądem. Celem było uzyskanie najwyższej wierności portu aplikacji na iPada do HTML5.

N2N-Apps to firma z branży oprogramowania, która koncentruje się na tworzeniu nowej generacji aplikacji internetowych i mobilnych z technologią HTML5. Firma została sfinansowana w 2010 r. przez Jeremy'ego Chone'a. Po 11 latach doświadczeń w inżynierii i zarządzaniu w firmach Netscape, Oracle i Adobe postanowiła dzielić się swoją wiedzą z firmami, aby tworzyć wysokiej jakości aplikacje internetowe i mobilne. N2N-Apps koncentruje się na jakości i szybkości dostarczania treści.

Pobierz MathBoard do Chrome Web Store Pobierz MathBoard do Chrome Web Store (wersja bezpłatna)

Wymagania

Najważniejsze wymagania dla tego projektu przenoszenia HTML5:

  1. Wysokiej jakości port oryginalnej aplikacji na iPada – wygląd i interfejs.
  2. Dostosuj do docelowego formatu (np. komputer PC lub Mac z klawiaturą/myszą lub ekranem dotykowym).
  3. Stosuj wszystkie dostępne funkcje.
  4. Kierowanie głównie na przeglądarki HTML5.
  5. Przekształć aplikację w „bezserwerową”, tak aby działała w całości na kliencie i mogła być hostowana na serwerze statycznym lub w aplikacji w pakiecie Google Chrome.
  6. Utworzenie wersji 1.0 zawierającej wszystkie funkcje i rozwiązania problemów w mniej niż miesiąc.

Architektura

Architektura

Biorąc pod uwagę te wymagania, postanowiliśmy wybrać następującą architekturę:

  1. HTML5: nie ma żadnych wymagań dotyczących obsługi języka HTML4, więc zdecydowaliśmy się zacząć używać HTML5.
  2. jQuery: HTML5 ma wiele zaawansowanych selektorów, dzięki którym jQuery jest tak rewelacyjnymi elementami, ale i tak zdecydowaliśmy się pozostać przy jQuery, ponieważ daje nam to bardzo stabilny i dojrzały sposób na manipulowanie DOM i powiązanymi zdarzeniami. Jedną z zalet tej metody jest to, że jest ona bardziej skoncentrowana na DOM, co zwykle sprawia, że projekt i implementacja aplikacji są bardziej zbliżone do HTML.
  3. SnowUI: jQuery to świetny interfejs API i sprawdzone metody pracy z DOM, ale w przypadku aplikacji HTML5 MathBoard potrzebna była struktura MVC lub MVP do administrowania różnymi widokami. SnowUI to prosta, ale zaawansowana platforma MVC uzupełniająca jQuery. Zapewnia on mechanizm MVC zorientowany na DOM oraz elastyczny sposób tworzenia niestandardowych komponentów, jednocześnie pozostawiając deweloperowi aplikacji możliwość korzystania z dowolnej biblioteki widżetów/elementów sterujących lub kodu niestandardowego, którą uzna za optymalny.

Uwagi na temat iPada na PC

Podczas przenoszenia aplikacji do HTML5 na komputerach PC musieliśmy kilka razy zmodyfikować jej wygląd i sposób interakcji z nią.

Orientacja ekranu

Urządzenie iPad MathBoard jest zorientowane wyłącznie w pionie, co nie było optymalne dla ekranów PC, ponieważ są zwykle używane w orientacji poziomej. W rezultacie zmieniliśmy układ interfejsu i przesunęliśmy panel ustawień na prawą stronę w widoku przesuwnym (animowanym przez przejścia CSS3).

Orientacja ekranu
Orientacja ekranu iPad a orientacja ekranu HTML5

Metoda wprowadzania: klawiatura/mysz vs. dotyk

Kolejną kluczową różnicą między wersją na iPada a wersją internetową jest interfejs do wprowadzania danych. Na iPadzie dostępny jest tylko interfejs dotykowy, a na komputerze PC – zarówno mysz, jak i klawiatura.

Sterowanie wprowadzaniem MathBoard na iPadzie jest bardzo dopracowane. Chcieliśmy, by w interfejsie internetowym była taka sama wysoka jakość. Rozwiązaniem było dodanie obsługi skrótów klawiszowych i replikację elementów sterujących interfejsu za pomocą pozycjonowania CSS. Port HTML5 był wspaniały:

Elementy sterujące interfejsu
Ustawienia iPada a ustawienia wersji HTML5

Podobnie jak w interfejsie iPada, użytkownik może kliknąć strzałkę w lewo lub w prawo, aby zmienić wartość elementu sterującego. Linię pionową można też przeciągnąć, aby szybko zmienić wartości. W przypadku click i keydown zaimplementowano funkcję powtarzania, dzięki czemu użytkownicy mogą przyspieszyć zmianę wartości po naciśnięciu myszy lub klawiatury.

Dodano obsługę klawisza Tab, aby umożliwić przejście z jednego pola do wprowadzania danych, a strzałki ← i → przełączają się między wartościami.

Jedną z funkcji wersji na iPada, która nie miała sensu dla interfejsu PC, była tablica rysunkowa. Wdrożenie tej funkcji mogłoby być wymyślne, ale rysowanie liczb za pomocą myszy nie jest zbyt praktyczne. Zdecydowaliśmy się więc poświęcić więcej czasu na dopracowanie interfejsu klawiatury niż na wdrożenie deski kreślarskiej.

Funkcje HTML5

W internetowej wersji MathBoard korzystamy z wielu funkcji HTML5:

Pamięć lokalna

MathBoard umożliwia użytkownikom zapisywanie quizu w celu jego późniejszego odtworzenia. HTML5 MathBoard implementuje tę funkcję za pomocą localStorage HTML5 za pomocą interfejsu SnowUI DAO.

Wybór localStorage był oczywisty, ponieważ dane były wystarczająco proste i nie wymagały zaawansowanego indeksowania. Wszystkie quizy przechowujemy w jednym formacie JSON, JSON.stringify jako tekst.

SnowUI DAO to prosty kod interfejsu CRUD, który pozwala interfejsowi pobierać dane bez obaw o to, jak są one faktycznie przechowywane. Implementacja DAO realizuje szczegóły dotyczące miejsca na dane.

W MathBoard wymagania dotyczące miejsca na dane były bardzo proste. Musieliśmy przechowywać tylko ustawienia użytkownika i dane quizu. Oba te typy są przechowywane jako ciągi JSON w pliku localStorage.

W przypadku wartości ustawienia DAO wygląda więc np. tak:

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();
})());

Po zarejestrowaniu tego DAO w settingValue interfejs użytkownika może wykonać to wywołanie bez obaw o logikę magazynu:

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

Czcionki CSS3

MathBoard używa niestandardowych czcionek. Dzięki obsłudze czcionek CSS3 dodanie prawdziwej czcionki „Chalkduster” do naszej aplikacji okazało się bardzo proste.

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

A ponieważ była to czcionka domyślna dla prawie całego tekstu w aplikacji, ustawiliśmy ją jako domyślną dla treści.

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

Gradient CSS3, cień, zaokrąglone rogi

Wszystkie gradienty, cienie, przezroczystość i zaokrąglone rogi są wykonywane za pomocą CSS3. W porównaniu z interfejsem użytkownika w formacie .png okazał się wielkim sukcesem.

Wykorzystaliśmy też zaawansowane właściwości CSS3, aby dostosować wygląd i styl paska przewijania i nadać mu bardziej subtelny charakter (informacje na temat stylu pasków przewijania w przeglądarkach WebKit można znaleźć na stronie http://webkit.org/blog/363/styling-scrollbars/).

Przejścia CSS3

W przypadku HTML5 MathBoard zreplikowaliśmy wszystkie animacje na iPadzie, a nawet dodaliśmy nową z przesuwanego prawego panelu. Dzięki przejśćom CSS3 dodanie animacji było proste i pozwalało uzyskać najlepszą wydajność.

W aplikacjach mieliśmy 3 główne animacje.

1) Przesuwny panel po prawej stronie

Pierwsza animacja znajduje się w panelu po prawej stronie (#rightPane), które zamyka się, gdy użytkownik rozpocznie nowy test, i przesuwa się po jego zakończeniu. Do utworzenia tego efektu użyliśmy poniższego przejścia CSS i wywołaliśmy je za pomocą JavaScriptu. Domyślny styl elementu rightPane jest otwarty:

#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;
}

Gdy użytkownik rozpoczyna test, nasza logika JavaScriptu przenosi panel:

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

Kilka uwag na temat tej implementacji:

  1. Biorąc pod uwagę, że rozmiary aplikacji są stałe, mogliśmy użyć klasy CSS „.close” i zakodować na stałe pozycję zamknięcia w taki sam sposób, w jaki zakodujemy na stałe otwartą klasę.
  2. Mogliśmy też użyć CSS „translate”, co byłoby skuteczniejsze niż animowanie właściwości „left” panelu. Dotyczy to zwłaszcza urządzeń mobilnych (takich jak urządzenia z iOS), na których przekształcenia 3D są akcelerowane sprzętowo.
  3. W tym przypadku właściwość setTimeout nie jest bezwzględna, ponieważ pierwotne położenie zostało ustawione przed modyfikacją. Pozwala to jednak przeglądarce na zrekompensowanie animacji, wyświetlając test tuż przed przesunięciem panelu prawo.

2) Animacja okna dialogowego Ustawienia

Gdy użytkownik kliknie ustawienie po prawej stronie, od dołu ekranu pojawi się okno ustawień i przewinie się w dół do odpowiedniej sekcji.

W tym celu przeprowadziliśmy podobne przejście do panelu po prawej stronie. Jedyne, co zajęło nam trochę czasu, było skomplikowanie problemu przy pierwszym pojawieniu się okna dialogowego. Aby nakazać przeglądarce buforowanie interfejsu okna, wyświetliliśmy go raz i przewinęliśmy do niego. Najpierw próbowaliśmy użyć konta display: none. To podejście było nieprawidłowe, ponieważ przeglądarka uznała, że okno nie musi być wyświetlane. Rozwiązaniem było wyświetlanie ustawień za pomocą elementu z-index: -1 podczas inicjowania, dzięki czemu są one niewidoczne dla użytkownika, ale były widoczne dla przeglądarki.

3) Powodzenie testu lub nieprawidłowa animacja wiadomości

Trzecia animacja jest w praktyce dwa w jednym. Gdy pojawi się komunikat „sukces” lub „niepoprawny”, najpierw przeskaluj do określonego punktu, poczekaj na odrobinę, a na koniec jeszcze większy i zniknij. Używamy do tego 2 stylów animacji CSS3 i zarządzamy nimi za pomocą JavaScriptu w zdarzeniu 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 dźwięku

Gdy użytkownik odpowie na test, aplikacja informuje o sukcesie lub niepowodzeniu. Najprostszym rozwiązaniem było użycie tagu audio i wywołanie użytkownika play() za jego pomocą. Te bity audio są dodawane do strony głównej aplikacji:

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

Podsumowanie

HTML5 naprawdę wprowadza nową generację aplikacji internetowych, komputerowych i mobilnych. CSS3 odegrał kluczową rolę w dostosowaniu wyglądu i stylu aplikacji do poziomu zaawansowania MathBoard na iPada. Pamięć w formacie HTML5 idealnie pasowała do naszych wymagań dotyczących trwałości danych, a prostota obsługi dźwięku w HTML5 pozwoliła nam dokładnie odtworzyć aplikację na iPada.