案例研究 - HTML5 MathBoard

Jeremy Chone
Jeremy Chone

简介

MathBoard 应用

iPad 上的 MathBoardPalaSoftware 应用,它是一款高度精致的应用,拥有许多细微但自然的动画,以及独特的逼真外观和风格。目标是将 iPad 应用的最高保真度移植到 HTML5。

N2N-Apps 是一家软件开发公司,专注于使用 HTML5 技术构建新一代 Web 应用和移动应用。该公司在 2010 年由 Jeremy Chone 资助,在 Netscape、Oracle 和 Adobe 积累了 11 年的工程和管理经验后,该公司决定与企业分享自己的专业知识,构建高质量的 Web 应用和移动应用。N2N-Apps 注重交付质量和速度。

下载 Chrome 应用商店的 MathBoard 下载 Chrome 应用商店的 MathBoard(免费版)

使用要求

此 HTML5 移植项目的关键要求如下:

  1. 原始 iPad 应用外观和风格及界面的高保真端口。
  2. 适应目标设备外形规格(即配备键盘/鼠标的 PC/Mac,而不是触摸屏)。
  3. 实现 100% 适用的功能。
  4. 主要定位到 HTML5 浏览器。
  5. 将应用程序设置为“无服务器”,这样该应用程序就完全在客户端上运行,而且可以托管在静态服务器或 Google Chrome 封装应用程序上。
  6. 用不到 1 个月的时间制作一个 1.0 版,其中包含所有功能但解决问题。

架构

架构

鉴于此要求,我们决定采用以下架构:

  1. HTML5:由于我们没有任何 HTML4 支持要求,因此我们决定以 HTML5 为基础。
  2. jQuery:虽然 HTML5 中有许多高级选择器使 jQuery 变得如此出色,但我们还是决定继续使用 jQuery,因为 jQuery 为我们提供了一种非常可靠和成熟的方式来操控 DOM 和相关事件。jQuery 还具有更加以 DOM 为中心的优势,这使得应用的设计和实现更接近 HTML。
  3. SnowUI:jQuery 提供了一个出色的 API 和使用 DOM 的最佳做法,但是,对于 HTML5 MathBoard 应用,我们需要一个 MVC 或 MVP 样式框架来编排所有不同的视图。SnowUI 是一个基于 jQuery 的简单但强大的 MVC 框架。它提供了一种以 DOM 为中心的 MVC 机制以及构建自定义组件的灵活方式,同时让应用开发者有机会使用他或她认为最佳的任何 widget/控件库或自定义代码。

从 iPad 连接 PC 的注意事项

将应用移植到 HTML5 以供 PC 端使用时,我们必须对应用的设计和用户互动做出一些修改。

屏幕方向

iPad MathBoard 完全是垂直方向,这并不是 PC 显示屏的最佳选择,因为它们通常以水平方式使用。因此,我们重新组织了界面设计,并将设置面板移到右侧,采用滑动视图(由 CSS3 过渡效果添加动画效果)。

屏幕方向
iPad 与 HTML5 屏幕方向

输入:键盘/鼠标与触摸

iPad 版本和 Web 版本之间的另一个主要区别是输入接口。iPad 上只有触摸界面,而在 PC 上,您需要同时考虑鼠标和键盘。

iPad 上的 MathBoard 输入控件经过精心打磨。我们希望在网页界面中实现同样的高保真度表示法。解决方案是添加对键盘快捷键的支持,以及使用 CSS 定位来复制界面控件。移植到 HTML5 的功能非常简单:

界面控件
iPad 与 HTML5 版本设置

与在 iPad 界面中一样,我们允许用户点击左右箭头来更改控件的值。也可拖动垂直线以快速更改值。为 clickkeydown 实现了重复行为,以便用户能够在按下鼠标或键盘时加速值更改。

添加了对 TAB 的支持,以便从一个输入字段移动到另一个输入字段,并且 ← 和 → 箭头可在值之间循环切换。

iPad 版本中有一个对 PC 界面没有太大意义的功能是绘图板。虽然实现它可能很华丽,但使用鼠标绘制数字并不是很实际。相反,我们决定花更多时间来完善键盘界面,而不是实现绘图板。

HTML5 功能

在网页版 MathBoard 中,我们使用了很多 HTML5 功能:

本地存储空间

MathBoard 允许用户保存测验,以便日后重温。HTML5 MathBoard 通过 SnowUI DAO 接口使用 HTML5 localStorage 来实现此功能。

localStorage 是一个自然的选择,因为数据足够简单,并且不需要高级索引编制。我们以一种 JSON 格式存储所有测验,并以文本形式进行 JSON.stringify 存储。

SnowUI DAO 是一个简单的 CRUD 接口封装容器,可让界面提取数据,而无需担心数据的实际存储方式。DAO 实现会处理存储细节。

在 MathBoard 中,存储要求非常简单。我们只需要存储用户设置和测验数据。两者均以 JSON 字符串形式存储在 localStorage 中。

例如,设置值的 DAO 如下所示:

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

settingValue 注册此 DAO 后,界面可以进行以下调用,而无需担心存储逻辑:

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

CSS3 字体

MathBoard 使用自定义字体。得益于 CSS3 字体的支持,在应用中添加“Chalkduster”真实字体变得轻而易举:

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

此外,由于此字体是应用中几乎所有文本的默认字体,因此我们将其设为默认的正文。

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

CSS3 渐变、阴影、圆角

所有的渐变、阴影、透明度和圆角效果都是通过 CSS3 实现的。 与传统的 .png 界面显示方式相比,这确实是一种真正的游戏存档方式。

我们还使用高级 CSS3 属性来自定义滚动条的外观和风格,使其更加精细(如需了解如何在 WebKit 浏览器中设置滚动条的样式,请参阅 http://webkit.org/blog/363/styling-scrollbars/)。

CSS3 过渡

对于 HTML5 MathBoard,我们复制了 iPad 的所有动画,甚至为右滑面板添加了一个新动画。得益于 CSS3 过渡,添加动画变得轻而易举,并且可以实现最佳性能。

应用中有三个主要的动画。

1.) 向右滑动的窗格

第一个动画位于右侧窗格 (#rightPane) 上,该动画会在用户开始新测验时关闭,在用户结束测验时打开。为了创建这种效果,我们使用了以下 CSS 转场,并通过 JavaScript 触发它。rightPane 的默认样式为打开样式:

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

当用户开始测验时,我们的 JavaScript 逻辑会移动面板:

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

关于此实现的一些说明:

  1. 鉴于应用大小是固定的,我们可以使用 CSS 类“.close”,并对关闭位置进行硬编码,就像对打开位置进行硬编码一样。
  2. 我们还可以使用 CSS“translate”,这会比为窗格的“left”属性设置动画效果要好。对于 3D 转换进行硬件加速的移动设备(如 iOS)来说尤其如此。
  3. 在这种情况下,setTimeout 并非绝对必要,因为原始位置是在修改之前设置的。不过,它可让浏览器在将 rightPane 滑入之前显示测验,从而使动画更流畅。

2.) “设置”对话框动画

当用户点击右侧的设置时,设置对话框会从屏幕底部显示,并向下滚动到相应部分。

为此,我们对右侧窗格进行了类似的过渡。唯一需要花时间解决的是对话框首次出现的卡顿问题。 为了指示浏览器缓存对话框界面,我们最终显示了该对话框界面一次,并滚动到该界面上。起初,我们尝试使用 display: none。这种方法是错误的,因为浏览器认为不需要显示该对话框。解决方法是在初始化时使用 z-index: -1 显示设置,使其对用户不可见,但对浏览器可见。

3.) 测验成功或错误消息动画

第三个动画实际上是二合一。当出现“成功”或“错误”消息时,首先缩放到某个点,稍等片刻,最后再放大并消失。为此,我们有两种 CSS3 动画样式,并通过 JavaScript 对 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);

音频标记

当用户回答测验时,应用会发出成功或失败的声音。最简单的选择是使用音频标记并对它们调用 play()。以下音频位会添加到应用的主页面中:

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

总结

HTML5 确实为新品种网络、桌面和移动应用带来了新的可能。 CSS3 在自定义应用的外观和风格方面发挥了重要作用,它与适用于 iPad 的 MathBoard 的高复杂性完美契合,HTML5 存储非常适合我们的数据持久化,而 HTML5 音频的简易性让我们得以完美地复制 iPad 应用。