用javascript和PhoneGap 3.0.0加速计制作移动app

来源:互联网 发布:万国数据上市吗 编辑:程序博客网 时间:2024/06/12 09:45

AndroidiOS平台继续竞争的时候,允许开发人员构建跨平台应用程序的库越发具有吸引力,其中最为突出的便是PhoneGap库。在本教程中,我们将建立一个硬件感知应用程序,用JavaScript 来处理设备加速计。

如果你还没有下载最新版的PhoneGap framework,那再简单不过,假设你已经安装了NodeJS。一旦你再装上PhoneGap,我们便可以创建应用程序。

1)通过输入如下命令行来创建PhoneGap应用程序。

$ phonegap create accelerate$ cd accelerate$ phonegap local plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-device-motion.git

注意应用程序将被创建在你的命令行中指定的任意文件夹内,请先确认是导向了你的目的文件夹。命令行指令的前两行是不言自明的,它们创建PhoneGap应用程序,调用加速和导航到刚创建的文件夹。

最新版的PhoneGap使用远程插件架构,因此我们必须用命令行最后一行的的代码来手动获取并安装加速插件。

2)打开加速文件夹并注意应用程序结构包含一个www文件夹。我们将在这里开展工作。

PhoneGap,移动,APP

Figure 1:PhoneGap应用程序文件夹构建

PhoneGap创建命令实际上是构建了一个小的示例应用程序。如果你加载index.html到一个浏览器,可以看到它的启动画面。如果你喜欢,可以在移动设备中运行整个应用程序。

在Android移动设备上运行该示例应用程序,用USB数据线连接该设备到你的电脑。发出如下命令用命令行路径指向你的项目文件夹:

$ phonegap build android$ phonegap run android

在iOS设备上运行示例应用程序,实际上更复杂,因为设备必须通过XCode被正确的配置。为测试而配置iOS设备,你必须用苹果开发程序注册。

我们将从应用程序中删除CSS文件夹,icon.png,图像文件夹和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>

正如你所看见的,有一些元标签在标题上,处理屏幕尺寸标准化。其余的代码是标准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

如果你得到了预期的报警框,并且其它一切都是正确的,则是时候为应用程序创建UI了(此刻你也许会想要在init()函数注释报警框)。我们将创建一个相当简单的UI,来向我们展示设备中的加速计生成的结果。我们将添加如下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以容纳CSS:

        <style>            body {                margin: 0px;            }            #footerTable {                width: 100%;            }            footer {                position:absolute;                bottom:0;                width:100%;                height:40px;                   background:#ccc;                }        </style>

在PhoneGap库中,加速对象有三种方式,分别是:

  •     getCurrentAcceleration()
  •     watchAcceleration()
  •     clearWatch()

第一种方式,getCurrentAcceleration(),将获取一个当函数在执行时加速计读取的快照。watchAcceleration()将返回加速计读取直到clearWatch()命令被发出。我们将使用watchAcceleration(),以便能在一段时间内看到加速。

watchAcceleration()方式返回一个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()方式的三个参数将发出call back,反之亦然。一个频率对象用加速计在毫秒中被取的样来设置频率。

success()和failure()的收call back该是相当直接的。在success()call back中,一个加速对象被传到函数,它包含了读取x/y/z轴的属性。failure() call back则是简单的输出一个错误信息。

此刻将是有一次测试你的应用程序的好时机,看看是否一切都工作正常。再一次,构建并运行你的应用程序发布如下命令:

$ phonegap run android

如果一切工作正常,在移动设备的时候,你则应该在屏幕底部更新看看X/Y/Z的解析。慢慢沿着不同的轴向移动设备,注意X/Y/Z的反映。

PhoneGap,移动,APP

Figure 2:注意屏幕底部的显示。

现在我们将让应用程序变得更有趣一些,用加速计使对象绕屏移动,通过HTML添加对象本身,然后用加速计的读数来决定速率和移动方向。作为准备,我们可以为应用程序添加一个canvas然后将一个对象放入其中。为了添加这个canvas,我们将添加一个canvas元素到body第一行。

<canvas id="myCanvas" ></canvas>

我们还将标准化HTML和body的宽度、高度和margin css属性以防万一。添加如下选择器和规则到你的CSS。

            {                width: 100%;                height: 100%;                margin: 0px;            }

用一张叫做“crosshair.png”的图像。我们将加载它到canvas在int()事件中。你将要为canvas的context和目标设置cnv,使得图像作为全局脚本的顶端。

照如下方法修改你的int()函数:

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变量用来引用我们将做大量工作的context对象。把canvas想作是隐形层将会很有用。

我们用context对象、cnv来设置canvas的宽高属性。为顾及我们已经在底端显示中创建的output bar,得从高度中减去40。我们初始化目标变量为一个图像目标并提供源图像到src属性。

我们要确保图像在我们试图展示它之前已经被加载,因此我们设置一个匿名函数,它在图像对象调用目标加载时被调用。在那时我们回执图像并做一些简单的数学把它放到屏幕中心。最终我们配置了加速计。

这是又一个在你的设备上测试程序的绝佳时机。

PhoneGap,移动,APP

Figure 3: canvas后的应用程序和图像已经被添加到canvas。

现在,当倾斜设备时,图像将会移动,加速计做出反应。大多数工作将在success() callback函数中完成。但是,我们还可以让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到你的script开始时的全局列表。你还将注意到在init()处理捕捉图像位置期间,xPos和yPos变量被设置,你同样也需要添加他们到全局列表。最后,降低频率值到25,我们就可以每25毫秒从加速计获取结果。现在到success()callback函数:

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

更新屏幕底部的显示栏后,clearRect()方式被canvas对象移除。这在刷新图像之前,在更新的位置清理了canvas。clearRect()方式需要一个启动点和你想要清理的宽高数据。我们清理整个canvas,所以我们提供它的完整宽高。

接下来我们在刷新之前更新xPos和yPos。必须否定xPos,才能让图像按照用户倾斜移动设备的方向移动。xPos和yPos均乘以1.5以便移动图像稍微快些。最后,drawImage()被调用,是它在新的位置绘制图像。

再一次测试你的应用程序,它应该是沿着设备倾斜轴而移动的。当然,为了挑战自我,你可以创建额外的代码,防止图像从边缘脱落。

如你所见,PhoneGap使得进入设备硬件更加容易,就像这加速计,包含在你的基于JavaScript的移动应用程序。