使用 Javascript 和 PhoneGap 3.0.0 进行移动加速计编程





5.00/5 (4投票s)
在本教程中,我们将构建一个硬件感知型应用程序,该应用程序使用 Javascript 与设备的加速计进行交互。
随着 Android 和 iOS 平台不断分化,允许开发人员构建跨平台应用程序的库日益受到关注。PhoneGap 是其中最突出的库之一。在本教程中,我们将构建一个硬件感知型应用程序,该应用程序使用 Javascript 与设备的加速计进行交互。
如果您还没有下载最新版本的 PhoneGap 框架,那么安装过程非常简单。假设您已安装 NodeJS,安装只需一行命令。安装完 PhoneGap 后,我们就可以构建您的应用程序了。
分步指南
1) 通过在命令行中输入以下命令来创建 phone gap 应用程序
$ phonegap create accelerate $ cd accelerate $ phonegap local plugin add https://git-wip- us.apache.org/repos/asf/cordova-plugin-device-motion.git
请注意,应用程序将在您命令行指向的任何文件夹中创建。请务必先导航到您的目标文件夹!命令行指令的前两行不言自明。它们创建了一个名为 accelerate 的 PhoneGap 应用程序,并导航到刚刚创建的文件夹。
最新版本的 PhoneGap 使用远程插件架构,因此我们必须使用最后一行命令行代码手动获取并安装加速计插件。
2) 打开 accelerate 文件夹,注意应用程序 结构 中包含一个 www 文件夹。这是我们将进行工作的地方。
PhoneGap 的 create 命令实际上会构建一个小型示例应用程序。如果您将 index.html 页面加载到浏览器中,您可以看到它的启动画面。如果您愿意,也可以在移动设备上实际运行整个应用程序。
要在 Android 移动设备上运行示例应用程序,请通过 USB 转 miniUSB 数据线将您的设备连接到计算机。将命令行路径指向您的项目文件夹,然后发出以下命令
$ phonegap build android $ phonegap run android
在 iOS 设备上运行示例应用程序实际上更复杂,因为设备必须通过 XCode 正确配置。要为测试配置 iOS 设备,您必须注册 Apple Developer Program。
实际上,我们将从应用程序中删除 CSS 文件夹、icon.png、img 文件夹和 js 文件夹。您可以在您喜欢的 文本编辑器中打开 index.html。打开文件后,删除与示例应用程序相关的代码。您应该只剩下类似这样的内容
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<script type="text/javascript" src="phonegap.js"></script>
<title>Accelerate</title>
</head>
<body>
</body>
</html>
如您所见,head 中有几个元标签用于处理屏幕尺寸的归一化。其余代码是标准的 HTML。我们将首先设置一个初始化例程,以便在运行任何代码之前知道设备和 PhoneGap 库都已准备就绪。
我们将把以下 <script>
元素添加到 <head>
的 文档 中,就在 <title>
之前。
<script> window.onload = function() { //init(); document.addEventListener("deviceready", init, false); } function init() { alert("Ready!"); } </script>
init()
函数将是我们的应用程序入口点。您会注意到与 window.onload
事件关联的匿名函数向应用程序添加了一个“deviceready
”监听器。此事件将告诉我们设备和 PhoneGap 库何时已准备好与用户交互。为了方便起见,我还注释掉了对 init()
的调用,以防我需要进行浏览器测试。由于“deviceready
”事件是 PhoneGap 库的一部分,它在浏览器中不起作用。
这是一个很好的停止和测试点。再次,在连接 Android 设备并设置好命令行指向您的应用程序文件夹后,发出以下命令
$ phonegap run android
如果您看到预期的警报框并且其他一切正常,那么是时候为应用程序创建用户界面了。(此时,您可能想注释掉 init()
函数中的警报框。)我们将创建一个相当简单的用户界面,显示加速计生成的设备读数。我们将把以下 HTML 添加到 body 元素中
<footer>
<table id="footerTable">
<tr>
<td>X: <span id="xOut"></span></td>
<td>Y: <span id="yOut"></span></td>
<td>Z: <span id="zOut"></span></td>
</tr>
</table>
</footer>
在文档 head 中添加一个 style 元素来包含 CSS
<style> body { margin: 0px; } #footerTable { width: 100%; } footer { position:absolute; bottom:0; width:100%; height:40px; background:#ccc; } </style>
在 PhoneGap 库中,acceleration 对象有三个方法。它们是
getCurrentAcceleration()
watchAcceleration()
clearWatch()
第一个方法 getCurrentAcceleration()
将在实现该函数时获取加速计读数的快照。watchAcceleration()
将返回加速计的读数,直到发出 clearWatch()
命令。对于我们的应用程序,我们将使用 watchAcceleration()
,以便我们可以查看一段时间内的加速度。
watchAcceleration()
方法返回一个 ID 值,该 ID 值以后可用于停止加速计。这一点很重要,因为我们不希望在不再需要加速计时,加速计还在消耗宝贵的资源。
编辑您的代码,使其如下所示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<style>
body {
margin: 0px;
}
#footerTable {
width: 100%;
}
footer {
position:absolute;
bottom:0;
width:100%;
height:40px;
background:#ccc;
}
</style>
<script type="text/javascript" src="phonegap.js"></script>
<script>
var watch = 0;
window.onload = function()
{
//init();
document.addEventListener("deviceready", init, false);
}
function init()
{
watch = navigator.accelerometer.watchAcceleration(success, failure, {frequency: 100});
}
function success(accel)
{
document.getElementById("xOut").innerHTML = accel.x;
document.getElementById("yOut").innerHTML = accel.y;
document.getElementById("zOut").innerHTML = accel.z;
}
function failure()
{
alert("Error");
}
</script>
<title>Hello World</title>
</head>
<body>
<footer>
<table id="footerTable">
<tr>
<td>X: <span id="xOut">0</span></td>
<td>Y: <span id="yOut">0</span></td>
<td>Z: <span id="zOut">0</span></td>
</tr>
</table>
</footer>
</body>
</html>
我们已经添加了使加速计工作的基本代码。您会注意到 init()
函数包含一行非常重要的代码
watch = navigator.accelerometer.watchAcceleration(success, failure, {frequency: 100});
这行代码基本上配置并开启了加速计。watchAcceleration()
方法中的三个参数分别是:如果加速计成功获取设备移动信息,则调用的回调函数;如果加速计失败,则调用的失败回调函数;以及一个频率对象,用于设置加速计的采样频率(以毫秒为单位)。在脚本开头全局声明的 watch 变量用于捕获 watch ID。
success()
和 failure()
回调函数应该看起来相当直接。在 success()
回调函数中,一个 acceleration 对象被传递到函数中,它包含 x、y 和 z 轴读数的属性。failure()
回调函数目前只是输出一条错误消息。
现在是时候再次测试您的应用程序,看看到目前为止一切是否正常工作。同样,要构建和运行您的应用程序,请发出以下命令
$ phonegap run android
假设一切正常,您应该看到屏幕底部 X Y 和 Z 的读数随着您移动设备而更新。缓慢移动设备,并注意当您沿不同轴移动设备时 X、Y 和 Z 如何反应。
现在,我们将让我们的应用程序变得更有趣。让我们使用加速计在屏幕上移动一个对象。我们将通过 HTML 添加对象本身,然后使用加速计读数来确定运动的速度和方向。为了做好准备,让我们向应用程序添加一个 canvas,并在其上放置一个对象。要添加 canvas,我们将把一个 canvas 元素添加到 body 的第一行。
<canvas id="myCanvas" ></canvas>
我们还将标准化 html 和 body 的 width、height 和 margin CSS 属性,以防万一。将以下选择器和规则添加到您的 CSS 中。
html, body
{
width: 100%;
height: 100%;
margin: 0px;
}
在这个应用程序中,我使用了一个名为“crosshair.png”的 图像。我们将在 init()
事件中动态加载它到 canvas。您需要将 cnv(用于 canvas 上下文)和 target(用于图像)设置为脚本顶部的全局变量。
将您的 init()
函数修改为如下所示
function init()
{
var iW = window.innerWidth;
var iH = window.innerHeight;
cnv = document.getElementById('myCanvas').getContext("2d");
cnv.canvas.width = iW;
cnv.canvas.height = iH-40;
target = new Image();
target.src = "crosshair.png";
target.onload = function()
{
cnv.drawImage(target, (iW-(target.width))/2, (iH-
(target.height))/2);
}
watch = navigator.accelerometer.watchAcceleration(success,
failure, {frequency: 100});
}
这里有很多内容,所以让我们分解一下重要的代码。iW 和 iH 变量只是包含 屏幕尺寸。显然,移动设备的规格各不相同,因此我们要确保创建一个灵活的 canvas。cnv 变量用于引用我们将进行大部分工作的上下文对象。将 canvas 视为一个围绕 canvas 的不可见层会很有帮助。
我们使用上下文对象 cnv 来设置 canvas 的 width 和 height 属性。我们从高度中减去 40,以便为我们在显示底部已经创建的输出栏留出空间。我们将 target 变量初始化为 Image 对象,并为其 src 属性提供源图像。
我们希望确保图像已加载,然后再尝试显示它,因此我们设置了一个匿名函数,该函数在名为 target 的图像对象加载时调用。届时,我们将绘制图像,并进行一些简单的数学运算将其置于屏幕中央。最后,我们配置加速计。
这是在设备上测试应用程序的另一个绝佳时机。
现在,我们将让图像随着用户倾斜设备并响应加速计而移动。这项工作的大部分将在 success()
回调函数中完成,但是,我对 init()
函数做了一些更改,以实现更平稳的应用程序运行。这是修改后的 init()
函数
function init()
{
var iW = window.innerWidth;
var iH = window.innerHeight;
canvas= document.getElementById('myCanvas');
cnv = canvas.getContext("2d");
cnv.canvas.width = iW;
cnv.canvas.height = iH-40;
target = new Image();
target.src = "crosshair.png";
xPos = (iW-target.width)/2;
yPos = (iH-target.height)/2;
target.onload = function()
{
cnv.drawImage(target, xPos, yPos);
}
watch = navigator.accelerometer.watchAcceleration(success,
failure, {frequency: 25});
}
修改完 init()
函数后,将 canvas 添加到脚本开头的全局声明列表中。您还会注意到在 init()
过程中设置了 xPos
和 yPos
变量,以捕获图像的初始位置。您还需要将这些添加到全局列表中。最后,我将频率值减小到 25,因此我们将每 25 毫秒从加速计获取一次结果。现在进入 success()
回调函数
function success(accel)
{
document.getElementById("xOut").innerHTML = accel.x;
document.getElementById("yOut").innerHTML = accel.y;
document.getElementById("zOut").innerHTML = accel.z;
cnv.clearRect(0, 0, canvas.width, canvas.height);
xPos += -1*(accel.x * 1.5);
yPos += (accel.y * 1.5);
cnv.drawImage(target, xPos, yPos);
}
在更新屏幕底部的显示栏后,在 canvas 对象上调用 clearRect()
方法。这会在重新绘制图像到更新位置之前清除 canvas。clearRect()
方法需要一个起始点以及要清除的宽度和高度。我们正在清除整个 canvas,因此我们将 canvas 的宽度和高度作为参数提供。
接下来,我们在重新绘制之前更新 xPos
和 yPos
。xPos
需要取反,这样图像就会朝着用户倾斜设备的那个方向移动。xPos
和 yPos
都乘以 1.5,以使图像移动得稍微快一些。最后,调用 drawImage()
,它会在新的更新位置绘制图像。
再次测试您的应用程序,它应该会随着设备沿每个轴倾斜而移动。为了挑战自己,请创建一些额外的代码来防止图像从屏幕边缘掉落。
如您所见,PhoneGap 可以轻松访问设备硬件(如加速计),并将其包含在您的基于 Javascript 的移动应用程序中。
特别感谢 Adobe 布道师 Raymond Camden (www.raymondcamden.com) 的慷慨协助。