简介

iPad 上的 MathBoard 是 PalaSoftware 应用,是一款经过精心打磨的应用,具有许多细微但自然的动画,以及独特逼真的外观和风格。目标是将 iPad 应用以最高保真度移植到 HTML5。
N2N-Apps 是一家软件开发公司,专注于使用 HTML5 技术构建新一代 Web 和移动应用。该公司由 Jeremy Chone 于 2010 年创立。Jeremy Chone 在 Netscape、Oracle 和 Adobe 积累了 11 年的工程和管理经验,决定与企业分享其专业知识,帮助他们构建高品质的 Web 和移动应用。N2N-Apps 专注于交付质量和速度。
下载适用于 Chrome 网上应用店的 MathBoard 下载适用于 Chrome 网上应用店的 MathBoard(免费版本)
要求
此 HTML5 移植项目的主要要求如下:
- 原始 iPad 应用外观和界面的高保真移植。
- 适应目标设备规格(例如,配备键盘/鼠标的 PC/Mac 与触摸屏)。
- 实现 100% 的适用功能。
- 主要定位到 HTML5 浏览器。
- 使应用变为“无服务器”应用,以便应用完全在客户端上运行,并且可以托管在静态服务器或 Google Chrome 打包应用上。
- 在不到一个月的时间内,制作出包含所有功能(但不含问题解决器)的 1.0 版。
架构

根据这些要求,我们决定采用以下架构:
- HTML5:由于我们没有任何 HTML4 支持要求,因此决定以 HTML5 为基础。
- jQuery:虽然 HTML5 具有许多使 jQuery 如此出色的高级选择器,但我们还是决定坚持使用 jQuery,因为它提供了一种非常强大且成熟的方式来操控 DOM 和相关事件。jQuery 还有一个优势,就是更侧重于 DOM,这往往会使应用的设计和实现更接近 HTML。
- SnowUI:jQuery 提供了一个出色的 API 和与 DOM 交互的最佳实践,但对于 HTML5 MathBoard 应用,我们需要一个 MVC 或 MVP 风格的框架来协调所有不同的视图。SnowUI 是基于 jQuery 的简单而强大的 MVC 框架。它提供了以 DOM 为中心的 MVC 机制,并提供了一种灵活的方式来构建自定义组件,同时让应用开发者有机会使用他们认为最优的任何 widget/控件库或自定义代码。
从 iPad 传输到 PC 的注意事项
将应用移植到 HTML5 以供 PC 使用时,我们不得不对应用的设计和用户互动做出一些修改。
屏幕方向
iPad MathBoard 只能采用纵向模式,这对于 PC 显示屏来说并不理想,因为 PC 显示屏通常采用横向模式。因此,我们重新整理了界面设计,并将设置面板移到了右侧的滑动视图(通过 CSS3 过渡效果实现动画)。

输入:键盘/鼠标与触控
iPad 版和网页版之间的另一个主要区别在于输入界面。在 iPad 上,您只有触控界面,而在 PC 上,您需要同时考虑鼠标和键盘。
iPad 上的 MathBoard 输入控件经过了精心打磨。我们希望在 Web 界面中也能获得同样的高保真呈现效果。解决方案是添加对键盘快捷键的支持,并使用 CSS 定位来复制界面控件。移植到 HTML5 后,像素完全准确:

与 iPad 界面一样,我们允许用户点击左右箭头来更改控件的值。您还可以拖动垂直线来快速更改值。为 click
和 keydown
实现了重复行为,以便用户在按下鼠标或键盘时加快值更改速度。
添加了 TAB 键支持,以便从一个输入字段移动到另一个输入字段,并且 ← 和 → 键可循环切换值。
iPad 版中有一项功能在 PC 界面上没有多大意义,那就是画板。虽然实现起来很炫酷,但用鼠标绘制数字并不实用。相反,我们决定花更多时间优化键盘界面,而不是实现画板。
HTML5 功能
在 MathBoard 的网页版中,我们使用了许多 HTML5 功能:
本地存储空间
MathBoard 允许用户保存自己的测验,以便日后重玩。HTML5 MathBoard 使用 SnowUI DAO 接口通过 HTML5 localStorage
实现此功能。
由于数据足够简单且不需要高级索引,因此 localStorage
是自然之选。我们将所有知识问答都存储为 JSON 格式,并将其 JSON.stringify
为文本。
snowUI DAO 是一个简单的 CRUD 接口封装容器,可让界面提取数据,而无需担心数据的实际存储方式。DAO 实现会处理存储细节。
在 MathBoard 中,存储空间要求非常简单。我们只需存储用户设置和知识问答数据。这两者均存储在 localStorage
中,以 JSON 字符串的形式存储。
例如,设置值的 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”TrueType 字体添加到应用中:
@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);
关于此实现的一些说明:
- 由于应用大小是固定的,我们可以使用 CSS 类“.close”,并像对开启按钮一样对关闭按钮的位置进行硬编码。
- 我们还可以使用 CSS“translate”,其性能要优于为窗格的“left”属性添加动画效果。对于采用硬件加速 3D 转换的移动设备(例如 iOS 设备),这一点尤为重要。
- 在本例中,
setTimeout
并不是严格必须的,因为原始位置是在修改之前设置的。不过,它允许浏览器在滑动右侧窗格之前显示测验,从而使动画更流畅。
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 真正支持了新一代 Web、桌面和移动应用。 CSS3 有助于自定义应用的外观和风格,使其与 MathBoard for iPad 的高度复杂性相得益彰;HTML5 存储空间非常适合我们的数据持久化;HTML5 音频的简单性使我们能够精确复制 iPad 应用。