简介
iPad 上的 MathBoard 是 PalaSoftware 应用,它是一款高度精致的应用,拥有许多细微但自然的动画,以及独特的逼真外观和风格。目标是将 iPad 应用的最高保真度移植到 HTML5。
N2N-Apps 是一家软件开发公司,专注于使用 HTML5 技术构建新一代 Web 应用和移动应用。该公司在 2010 年由 Jeremy Chone 资助,在 Netscape、Oracle 和 Adobe 积累了 11 年的工程和管理经验后,该公司决定与企业分享自己的专业知识,构建高质量的 Web 应用和移动应用。N2N-Apps 注重交付质量和速度。
下载 Chrome 应用商店的 MathBoard 下载 Chrome 应用商店的 MathBoard(免费版)
使用要求
此 HTML5 移植项目的关键要求如下:
- 原始 iPad 应用外观和风格及界面的高保真端口。
- 适应目标设备外形规格(即配备键盘/鼠标的 PC/Mac,而不是触摸屏)。
- 实现 100% 适用的功能。
- 主要定位到 HTML5 浏览器。
- 将应用程序设置为“无服务器”,这样该应用程序就完全在客户端上运行,而且可以托管在静态服务器或 Google Chrome 封装应用程序上。
- 用不到 1 个月的时间制作一个 1.0 版,其中包含所有功能但解决问题。
架构
鉴于此要求,我们决定采用以下架构:
- HTML5:由于我们没有任何 HTML4 支持要求,因此我们决定以 HTML5 为基础。
- jQuery:虽然 HTML5 中有许多高级选择器使 jQuery 变得如此出色,但我们还是决定继续使用 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 显示屏的最佳选择,因为它们通常以水平方式使用。因此,我们重新组织了界面设计,并将设置面板移到右侧,采用滑动视图(由 CSS3 过渡效果添加动画效果)。
输入:键盘/鼠标与触摸
iPad 版本和 Web 版本之间的另一个主要区别是输入接口。iPad 上只有触摸界面,而在 PC 上,您需要同时考虑鼠标和键盘。
iPad 上的 MathBoard 输入控件经过精心打磨。我们希望在网页界面中实现同样的高保真度表示法。解决方案是添加对键盘快捷键的支持,以及使用 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 中,存储要求非常简单。我们只需要存储用户设置和测验数据。两者均以 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);
关于此实现的一些说明:
- 鉴于应用大小是固定的,我们可以使用 CSS 类“.close”,并对关闭位置进行硬编码,就像对打开位置进行硬编码一样。
- 我们还可以使用 CSS“translate”,这会比为窗格的“left”属性设置动画效果要好。对于 3D 转换进行硬件加速的移动设备(如 iOS)来说尤其如此。
- 在这种情况下,
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 应用。