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

示例项目:使用 Famo.us + Angular 创建移动应用程序

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2015 年 9 月 9 日

CPOL

7分钟阅读

viewsIcon

14964

在本文中,我将深入探讨 Famo.us 的方方面面。

我喜欢高性能的 JavaScript,也喜欢分享我认为它真正的潜力。在本教程中,我想重点介绍 Famo.us——它可以让您在屏幕上拥有流畅的动画,同时保持每秒 60 帧的丝滑流畅度。Famo.us 通过利用 CSS3 的基本属性 `-webkit-transform: matrix3d` 来实现这一点,该属性允许框架计算组合矩阵并跳过浏览器的渲染器。无需插件,无需下载,无需 hack。通过将此添加到每个 DIV,开发人员可以渲染组合矩阵并直接到 GPU。

这篇博文中,我更深入地讨论了 Famo.us 的细节。再次感谢Zack Brown的协助!我们开始吧。

完成本项目后,您将能够

  • 了解 Angular 在 Famo.us 应用程序中的工作原理
  • 发挥 JavaScript 的真正威力以及 HTML5 的优点
  • 创建流畅的动画

本项目的目标是说明您可以轻松地创建在移动应用程序上以接近原生速度运行的 HTML5 / JS 项目。

特点

  • 通过 Cordova,移动应用程序可以在 iOS 和 Android 上运行
  • Windows 10 通用应用可在 Windows 10 上原生运行
  • 本项目也可以作为托管网站运行,但我已将其最佳缩放为移动设备

要求

  • PC 或 Mac
  • Web 服务器
  • 跨平台测试矩阵(例如 BrowserStack、IDE 或适用于 EdgeHTML 的免费虚拟机,Microsoft Edge 的渲染引擎以及 Windows 10 上的托管 Web 应用内容)。

安装

  1. 从 GitHub 下载源代码
  2. 下载并安装 Web 服务器(我在 OS X 上使用 MAMP,或在 Windows 上的 Visual Studio 中使用内置的 IIS 服务器)

打开项目

  1. 启动您的 Web 服务器
  2. 导航到 famous-angular-Pokemon/app/

该项目设计用于在移动设备上运行,因此请使用浏览器中的移动模拟器以获得正确的视图。在 Chrome 桌面浏览器(375x667)的模拟器中,它在 iPhone 6 上的外观如下所示。

工作原理

访问数据库

我从PokeAPI获取所有信息,该 API 文档齐全,但缺少每只宝可梦的图片。对于图片,我只获取当前选定宝可梦的名称,并将其附加到此 URL 的末尾:http://img.pokemondb.net/artwork/。例如:http://img.pokemondb.net/artwork/venusaur.jpg 将引导您看到一张妙蛙花的图片。很巧妙,对吧?遗憾的是,他们没有提供 API。

每次用户按下“下一个”按钮时,都会在定义的最小值/最大值之间(例如 1-20)生成一个随机数,然后从数据库中提取与该数字匹配的宝可梦。看起来是这样的:

http://pokeapi.co/api/v1/pokemon/1/ 返回一只妙蛙花的 JSON 对象。您可以在此处尝试他们的 API。

遍历数据

然后,我遍历该 JSON 对象,并使用 $Scope 对象将找到的属性设置为 Angular 中的变量。

这是一个例子

  /*
   * Grab Pokemon from the DB
   */
  $scope.getPokemon = function () {  

    // Generate a random num and use it for the next pokemon
    getRandomInt($scope.minVal, $scope.maxVal);

    // Retrieve data from DB and draw it to screen
    $http.get($scope.dbURL + $scope.pokemonNum + "/")
      .success(function(data) {
        $scope.name       = data.name;
        $scope.imageUrl   = $scope.imgDbURL + $scope.name.toLowerCase() + '.jpg';

        /* 1) Empty out the current array to store the new items in there
         * 2) Capitalize the first character for each ability from the database
         * 3) Store that ability in a new abilityObj & add it into the abilities array
         */
        $scope.abilities.length = 0;
        for (var i = 0; i < data.abilities.length; i++){
         var capitalizedString = capitalizeFirstLetter(data.abilities[i].name);
         var abilityObj        = {name: capitalizedString };
          $scope.abilities.push(abilityObj);
        }

        $scope.hitPoints  = data. hp;
        var firstType     = data.types[0].name;
        $scope.types.name = capitalizeFirstLetter(firstType);
        determineNewBgColor();
      })
      .error(function(status){
        console.log(status);
        $scope.name = "Couldn't get Pokemon from the DB";
      });
  };

您可能会注意到,我还有其他一些函数,例如 capitalizeFirstLetter,它的作用正是如此。我希望将能力和类型(例如:poison、grass、flying)的首字母大写,因为它们是从数据库中以全小写字符返回的。

我还遍历了能力并将它们推送到一个能力对象,该对象如下所示:

   $scope.abilities       = [
    { name: "Sleep"},
    { name: "Eat"  }
  ];

数据库还会为某些宝可梦返回多种类型,例如喷火龙,它既是飞行系又是火系。但为了简单起见,我只想从数据库返回一种。

  $scope.types      = { name: "Grass" };

  var firstType     = data.types[0].name;

将其绘制到屏幕上

Famo.us 有两种绘制内容到屏幕的方式,通过创建“surface”,它们是包含文本、图像等的元素。

  1. JavaScript
  2. FA-Directives (HTML)

在这个应用程序中,我没有使用 JavaScript 来绘制 surface,而是选择只使用 FA (Famous-Angular) Directives,例如:

        <!-- Name-->
        <fa-modifier
            fa-origin    ="origin.center"
            fa-align     ="align.frontName"
            fa-size      ="size.frontName"
            fa-translate ="trans.topLayer">
            <fa-surface
                class    ="front-name-text">
                {{name}}
            </fa-surface>
        </fa-modifier>

主屏幕上宝可梦名称上方的文字。

您会注意到 surface 被 fa-modifier 包围。您可以在此处阅读有关它们的信息,但它们基本上用于调整 surface 的属性,例如对齐、大小和原点。我花了一段时间才弄清楚对齐和原点之间的区别,以下是我的理解方式:

原点 任何 surface 上的参考点。如果我想绘制一个矩形并在屏幕上移动它,我需要决定这个矩形的哪个点将是我的起点。Famo.us 文档对此进行了很好的解释。值的布局如下:

  $scope.origin          = {
                         // X    Y 
   topLeft:                [0,   0  ],
   topRight:               [1,   0  ],
   center:                 [0.5, 0.5],
   bottomLeft:             [0,   1  ],
   bottomRight:            [1,   1  ]
  };

对齐 surface 在屏幕上的位置。当您更改对齐方式时,它会使用原点作为起点。

  $scope.align          =  {
                          // X        Y 
    frontName:             [0.50,    0.10],
    frontImg:              [0.50,    0.40],
    backImg:               [0.5,     0.38],
    center:                [0.50,    0.50]
  };

Angular 发挥作用的地方

现在,您可以在这里利用您所有的 Angular 技能和数据绑定来处理这里的 Angular 实现。如果您已经熟悉 Angular,那么这在这里并没有根本性的不同。

       <!-- Next button -->
        <fa-modifier
            fa-origin    ="origin.center"
            fa-align     ="align.nextBtn"
            fa-size      ="size.btn"
            fa-scale     ="scale.nextBtn.get()"
            fa-translate ="trans.topLayer">
            <fa-surface
                class    ="one-edge-shadow center-align next-btn"
                ng-click ="getPokemon(); nextBtnPressAnim(); frontImgAnim()">
                {{nextBtn}}
            </fa-surface>
        </fa-modifier>

此按钮出现在第一个屏幕上,只需从数据库加载另一个宝可梦。所有您熟悉的 ng (angular) 指令都在这里,例如 ng-click。我有多个函数(注意:它们不是用逗号分隔的)。

我还将 $scope.nextBtn 的值绑定到 HTML 中的 {{nextBTn}}

为了让 Famo.us 和 Angular 协同工作,我们需要在 JavaScript 文件的顶部包含 $Famo.us。以下是如何操作:

angular.module('famousAngularStarter')
  .controller('PokemonCtrl', ['$scope', '$http', '$famous', function ($scope, $http, $famous) {

    /* Inject famo.us to DOM */
    var View           = $famous['famous/core/View'                 ];
    var Modifier       = $famous['famous/core/Modifier'             ];
    var Surface        = $famous['famous/core/Surface'              ];
    var Transform      = $famous['famous/core/Transform'            ];
    var Transitionable = $famous['famous/transitions/Transitionable'];
    var Timer          = $famous['famous/utilities/Timer'           ];

没有动画的高性能应用程序会是什么样子?Famo.us 充满了动画,这使得入门变得容易。这是一个用于为主屏幕上的图像设置动画的示例。

  /*
   * @OnClick: Sets the opacity and scale for the front image when user clicks "Next" btn
   * 1) Turns opacity invisible quickly before returning to original opacity, revealing new Pokemon
   * 2) Turns scale down before quickly turning it back up to original size
   */
  $scope.frontImgAnim = function() {
    var hideDuration   =  200;
    var returnDuration = 1300;

    $scope.opac.imgFront.    set(0,           {duration: hideDuration,   curve: "easeIn"},
      function returnToOrigOpacity() {
        $scope.opac.imgFront.set(1,           {duration: returnDuration, curve: "easeIn"})
      }
    );
    $scope.scale.imgFront    .set([0.5, 0.5], {duration: hideDuration,   curve: "easeIn"},
      function returnToOrigSize() {
        $scope.scale.imgFront.set([0.8, 0.8], {duration: returnDuration, curve: "easeIn"})
      }
    )
  };

这里有几种曲线类型可供使用。您可以查看文档以获取更多信息。我还使用了一个回调函数 returnToOrigSize 来使图像先放大然后缩小回原始大小。

遇到的麻烦

在此过程中我遇到了一些问题。

  • FA-Directives 的属性设置为字符串
fa-origin    ="origin.center"

如果您有拼写错误,应用程序将仅使用该属性的默认值。这卡了我好几次,这就是为什么您会看到我将所有属性设置为一个对象,例如 align.frontName,以便于阅读。

  • 添加类

在 FA-Directives 中,您以字符串形式添加多个类,并且它们之间不使用逗号分隔。

            <fa-surface
                class    ="one-edge-shadow center-align next-btn"
                ng-click ="infoBtnPressAnim(); flip()">
                {{infoBtnText}}
            </fa-surface>

如果您尝试通过在 JavaScript 中创建 surface 来添加类,则需要传入一个字符串数组。

    var logo = new Surface({
        properties: {
             ...
        },
        classes: ['backfaceVisibility, class-two'] 
    });

我花了一段时间才理解这一点,因为我只在这个帖子中找到了解决方案。

  • Famo.us + Angular 似乎已弃用(目前如此)

在这个项目进行到一半时,我看到 Famo.us 正在开发框架的改进版本,其中包括混合模式。至少目前,Famous + Angular 无法利用这些新增功能。这并不意味着 FA 会消失,因为它工作得很好,只是您将无法获得最新功能。

资源

  • Famo.us Slack 聊天
  • BizSpark,提供免费的 Microsoft 开发许可证和 Web 托管
  • 如有疑问,请通过电子邮件与我联系
  • 了解如何将其变成适用于移动平台的 Cordova 应用

更多关于 JavaScript 的实践

本文是 Microsoft 技术传播者关于实用 JavaScript 学习、开源项目和互操作性最佳实践的 Web 开发系列文章的一部分,包括Microsoft Edge浏览器和新的EdgeHTML 渲染引擎

我们鼓励您使用dev.modern.IE上的免费工具,在各种浏览器和设备(包括 Windows 10 的默认浏览器 Microsoft Edge)上进行测试。

来自我们工程师和布道者的 Microsoft Edge 和 Web 平台深度技术学习

更多免费的跨平台工具和网络平台资源

© . All rights reserved.