65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2013年9月3日

CPOL

9分钟阅读

viewsIcon

37539

downloadIcon

1114

在本教程中,我们将构建一个硬件感知型应用程序,该应用程序使用 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 文件夹。这是我们将进行工作的地方。

 

图 1:PhoneGap 应用程序文件夹结构

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 如何反应。

图 2:注意屏幕底部的显示

现在,我们将让我们的应用程序变得更有趣。让我们使用加速计在屏幕上移动一个对象。我们将通过 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 的图像对象加载时调用。届时,我们将绘制图像,并进行一些简单的数学运算将其置于屏幕中央。最后,我们配置加速计。

这是在设备上测试应用程序的另一个绝佳时机。

图 3:添加 canvas 和图像后的应用程序。

现在,我们将让图像随着用户倾斜设备并响应加速计而移动。这项工作的大部分将在 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() 过程中设置了 xPosyPos 变量,以捕获图像的初始位置。您还需要将这些添加到全局列表中。最后,我将频率值减小到 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 的宽度和高度作为参数提供。

接下来,我们在重新绘制之前更新 xPosyPosxPos 需要取反,这样图像就会朝着用户倾斜设备的那个方向移动。xPosyPos 都乘以 1.5,以使图像移动得稍微快一些。最后,调用 drawImage(),它会在新的更新位置绘制图像。

再次测试您的应用程序,它应该会随着设备沿每个轴倾斜而移动。为了挑战自己,请创建一些额外的代码来防止图像从屏幕边缘掉落。

如您所见,PhoneGap 可以轻松访问设备硬件(如加速计),并将其包含在您的基于 Javascript 的移动应用程序中。

特别感谢 Adobe 布道师 Raymond Camden (www.raymondcamden.com) 的慷慨协助。

更多关于 PhoneGap 的精彩资源 

© . All rights reserved.