使用Famo.us创建高性能的移动UI

JavaScript开发人员社区热切欢迎Famo.us开源UI渲染框架于2014年Spring公开发布。 Famo.us承诺消除一些阻碍JavaScript和Web技术主导移动开发领域的最后瓶颈:缓慢的UI和糟糕的用户体验(UX)。

Famo.us以移动设备上的硬件图形处理单元(GPU)为目标,以实现尽可能最高的渲染帧速率,并且它添加了完善的物理引擎来实现令人满意的UX。 在为移动应用程序创建UI时,与Objective-C,Swift或Java™开发人员相比,JavaScript开发人员不再处于劣势。

本文介绍Famo.us的基本概念并探讨其设计。 然后,它动手处理了几个工作示例,包括一个典型的移动应用程序UI,您可以将其用作使用Famo.us开发的应用程序模板。 (请参阅下载以获取完整的示例代码。)

Famo.us如何工作

通过快速显示具有更改元素的连续页面(框架)来创建动画。 帧速率是每秒显示的帧数。 由于人类视觉的潜伏期,高帧频会产生运动的视觉错觉(电影背后的原理相同)。 为了在网页上创建动画,每帧都会修改元素的样式属性(位置,颜色和不透明度)。 这些属性的更新速度最终决定了UI的最大帧速率。 对于与Web应用程序的交互,每秒60帧(fps)被认为是平滑,类似于本机应用程序的UX的最佳速率。 当无法始终达到60 fps时,会出现不良的UX效果,例如颠簸和掉线(统称为Jank)。

Famo.us的核心是一个跨浏览器的高性能UI布局和优化库,具有自己的动画和物理引擎-用JavaScript编写。 Famo.us经过优化,可以在最短的时间内完成每帧的工作。 (最近的Famo.us基准测试表明,Famo.us在处理典型动画时每16.7 ms的帧可以花费少至1到2 ms,否则就没有性能开销。)然后,可以以最佳帧渲染目标UI。速率-通常至少为60 fps。 Famo.us项目致力于在所有后续版本中维持或改善此fps性能。

在操作上,Famo.us用其自己的高性能替代产品替换了典型的以DOM为中心的布局操作和2D或3D动画。 图1说明了Famo.us的内部工作原理。 浏览器的requestAnimationFrame() (rAF)回调函数针对每一帧调用Famo.us引擎(单例对象)。 每秒六十次对应于每帧60 fps或1 / 60s(16.7 ms)。 每个回调在Famo.us中被称为引擎刻度 。

图1. Famo.us库的操作
Famo.us内部运行方式的说明

Famo.us API

Famo.us API向开发人员展示了自己的一组高级可组合对象,例如表面 , 视图和小部件 。 您的Famo.us代码创建要渲染的场景图(在Famo.us中当前称为渲染树 ),连接事件处理,并指导或安排动画。

Famo.us场景图中的每个节点都是一个渲染节点 。 场景图被处理为渲染规范,并建立规范中间表示,Famo.us渲染组件在内部使用该中间表示来使目标的更新更加有效。

渲染组件以支持的帧速率(当前为60 fps)评估场景图,并将所需的更新输出到浏览器的DOM,Canvas元素或WebGL。 (Famo.us的beta实现仅针对浏览器的DOM。)Famo.us旨在在同一屏幕上输出到其任何受支持的目标,甚至同时(支持多模式操作 )。

表面和可渲染

在Famo.us,您撰写和动画renderables。 您使用的最低级别的通用可渲染对象是Surface 。 浏览器的DOM中显示的Surface<div>元素。 (如果检查Famo.us Surface ,则可以看到<div> 。)Famo.us中其他特殊类型的表面由其他HTML5元素表示:

  • Surface<div>
  • VideoSurface<video>
  • ImageSurface<img>
  • InputSurface<input>
  • CanvasSurface<canvas>

Surface类具有一个content字段。 在此字段中,您可以添加要在Surface上呈现HTML(在基础<div> )。

Famo.us不会干预您获取此content方式或位置,该content是呈现为HTML的字符串。 该字符串是任何模板,数据源或数据绑定技术的自然集成点。 此外,由HTML在呈现的Surface上形成的mini-DOM可以进行操作-除任何布局,包含或动画工作外,都应通过Famo.us完成。

使用Famo.us进行编程时,您可以提高性能和渲染灵活性,以换取直接对页面DOM进行即时模式操作。

与3D渲染库的比较

Famo.us的此体系结构类似于WebGL 3D渲染JavaScript库,包括Three.js和SceneJS。 了解异同可以帮助您快速掌握Famo.us:

  • 两种架构中的浏览器rAF触发帧渲染。
  • 在3D渲染库中,您将三角形和2D对象(例如墙或地板)和更高级的3D几何形状(例如金字塔,球体,立方体或多边形网格)放置并放置到场景图中。 在Famo.us中,您可以在场景图形中放置和放置2D曲面或更高级别的对象(例如视图或小部件)。
  • 在3D渲染库中,您可以通过在场景图中添加和链接转换节点(其中对象是叶子)来转换对象。 在Famo.us中,可以将修改器节点添加并链接到场景图中,其中表面或其他可渲染对象是叶子。
  • 在SceneJS中,可以使用JSON指定复杂的场景图,并通过图节点上的ID属性对其进行修改。 Famo.us有一个Scene组件,可用于通过JSON构建复杂的场景图。 您可以通过渲染节点上的ID属性对其进行修改。
  • 在3D库中,对象属性会在rAF回调中进行动画处理和补间。 在Famo.us中,在浏览器的rAF回调驱动的Famo.us 引擎的每个刻度上,都会更新和补间表面的属性(更常见的是可渲染对象)。
  • 3D库通常包含一个物理引擎,以使动画更加逼真。 Famo.us包含完整的物理引擎,可以使动画对用户更直观。
  • 即使3D场景中的所有对象都是由三角形组成的,但开发人员很少需要使用单个三角形,因为3D渲染库通常包括诸如球体和金字塔之类的常见几何形状的网格。 尽管Famo.us中的基本可渲染对象是表面,但由于该库包含许多预制的高级UI视图和小部件,因此您几乎不需要使用单个表面。
  • HTML在3D库中没有任何作用,除了Canvas元素是渲染3D视口的元素之外。 在Famo.us中,HTML是您在表面上呈现的内容,但是HTML不再定义UI页面的结构; 该结构在JavaScript代码中指定。 您不再需要管理<div><table>标记来控制布局。 CSS仅用于影响元素样式,不影响布局。 (HTML仍然很重要,因为当以DOM为目标时,所有可视元素都是HTML元素。)
  • 3D库的渲染组件通常以Canvas,WebGL和SVG输出为目标-支持WebGL,因为它几乎可以直接访问底层3D渲染GPU硬件。 Famo.us渲染组件的目标是Canvas,DOM和WebGL。 Famo.us具有DOM更新程序,该更新程序使用领先的浏览器提供的已知GPU优化来实现其性能目标。

使用Famo.us

看看实际的Famo.us应用程序可以帮助您锚定概念。 图2中的示例是Famo.us入门工具包中包含的默认应用程序,并且默认情况下也是由generator-famousgenerator-famous软件包generator-famous (请参见运行Famo.us的三种方法 )。 该应用程序将绕着y轴平移Famo.us徽标的呈现形式。

图2. generator-famous生成generator-famous生成的默认应用程序
旋转徽标默认Famo.us应用程序的屏幕截图

在main.js中,单独的ImageSurface由清单1中所示的代码创建。

清单1.创建ImageSurface (提供给DOM <img>)
var logo = new ImageSurface({
    size: [200, 200],
    content: '/content/images/famous_logo.png',
    classes: ['backfaceVisibility']
});

在清单1中, content选项对应于基础<img>标记的src属性。 classes选项将CSS类添加到HTML元素。 app.css中定义的backfaceVisibility CSS类可确保用户可以看到徽标的backfaceVisibility该类在app.css中定义为:

.backfaceVisibility {
  -webkit-backface-visibility: visible;
  backface-visibility: visible;
}

上下文 (与DOM节点相关联的微型DOM管理器)管理一个场景图,该场景图由节点内的所有DOM表示。 通常,您只有一个上下文实例(除非您正在从事特殊项目,例如多个透视图或平视显示器)。

修改器是Famo.us场景图中的渲染节点,它们修改位于其下方的渲染节点的某些属性(通常将转换应用于)。 您可以将多个修改器链接在一起,在这种情况下,转换矩阵会组合在一起,并且场景图的叶子始终是可渲染的。

在此示例中, centerSpinModifier包含一个origin属性和一个transform属性。 相对于所包含的父级(在本例中为Famo.us上下文)指定了origin属性。 图3显示了指定Famo.us origin的约定。

图3.设置origin属性的约定
具有标记位置的3x3网格,显示了设置原点属性的约定

图3中 ,九个点排列在3x3网格中。 [0.0]位于左上方,[1,1]位于右下方。 [0.5,0.5]是中心点。 其余点遵循此约定,例如,右上角[1,0]和左下角[0,1]。

centerSpinModifiertransform属性通过Transform.rotateY()返回一个绕y轴旋转的函数:

var initialTime = Date.now();
  var centerSpinModifier = new Modifier({
      origin: [0.5, 0.5],
      transform : function() {
          return Transform.rotateY(.002 * (Date.now() - initialTime));
      }
  });
mainContext.add(centerSpinModifier).add(logo);

此代码完成了图4中所示的简单场景图。

图4.默认应用程序的场景图
默认应用程序的场景图的插图。从上到下的节点是“上下文”,“旋转”修改器和徽标ImageSurface。

现在,Famo.us引擎评估内存中的场景图,并在rAF的驱动下有效地更新每帧的DOM,每秒大约更新60次。 每次, centerSpinModifer检查自initialTime以来经过的时间,并围绕y轴递增旋转徽标。 您可以轻松地调整0.002常数以改变旋转速度。

总结一下:

  1. 您创建logo ImageSurface
  2. 您创建一个Famo.us Modifier ,该Modifier是:
    • 将徽标设置为围绕上下文的中心旋转( origin = [0.5 0.5])
    • 使用围绕y轴逐渐旋转的transform
  3. Modifier添加到场景图,然后在Modifier正下方添加logo ImageSurface
  4. Famo.us引擎处理场景图并以rAF速率更新DOM,徽标不断旋转。

扩展示例

为了进一步说明默认示例,下一个示例旋转了10个徽标实例,以10x10正方形的形式布置,在x轴和y轴之间交替旋转。 图5显示了最终的应用程序。

图5.旋转了100个徽标实例的扩展应用
扩展应用程序的屏幕截图,带有100个旋转徽标实例

图6显示了此示例必须构造的场景图。

图6.扩展应用程序的场景图
旋转徽标应用程序的场景图插图

您可以看到此版本如何扩展前面的示例:

  • 现在,场景图具有100个分支,而不是1个。
  • 现在,每个分支都有两个修饰符。 在旋转修饰符之前创建并添加了另一个平移修饰符,以将徽标首先移动到所需位置。

如清单2所示,用于创建修饰符并将其添加到每个徽标的上下文的代码与第一个示例类似。 它包含对每个帧进行动画处理和更新的计算工作。

清单2.旋转100个徽标的扩展代码示例
var mainContext = Engine.createContext();
var initialTime = Date.now();
function rotY() {
        return Transform.rotateY(.002 * (Date.now() - initialTime));
    }
function rotX() {
        return Transform.rotateX(.002 * (Date.now() - initialTime));
    }

for (var i=0; i< 10; i ++)
  for (var j=0; j<10; j++) {
    var image =
        new ImageSurface({
            size: [50, 50],
            content: '/content/images/famous_logo.png'
        });
    var transMod =
       new Modifier({
              size: image.getSize.bind(image),
              transform: Transform.translate(j * 50, i * 50, 0)
            }
        );

    var rotMod =
        new Modifier({
            origin: [0.5, 0.5],
            // xor
            transform : (((i % 2) !== (j % 2)) ?  rotY  : rotX)
        });

    mainContext.add(transMod).add(rotMod).add(image);

这个应用程式有两个独立的转换功能,分别是rotY绕y轴旋转和rotX绕x轴旋转。 场景图的分支是在嵌套的i - j循环中创建的。 添加到每个分支的两个修饰符分别命名为transMod (徽标图像到位的翻译)和rotMod (徽标围绕其原点的旋转)。

为了在x轴和y轴旋转之间交替,通过以下方式交替更改rotModtransform属性:

transform : (((i % 2) !== (j % 2)) ?  rotY  : rotX)

与第一个示例一样,您在内存中设置了场景图,Famo.us引擎负责处理它并以rAF速率更新DOM。

动画的过渡和补间

在创建UI时,通常使用持续时间有限的动画。 一个示例是用户在到达滚动列表末尾时观察到的“反弹”。 另一个是从背面翻转一张扑克牌以露出其面Kong。

Famo.us通过Transitionable类支持过渡,该类表示可以随时间进行过渡的属性。 下一个示例显示了两个补间过渡的用法。

运行该应用程序时,您会在页面中间的Famo.us滚动视图中看到显示的developerWorks文章列表。 此列表在前10秒钟以恒定的速度绕y轴旋转。 然后,它猛烈地弹回并在接下来的10秒钟内反弹。 在进行这种持续时间有限的动画时,您可以连续滚动列表(如果使用的是桌面浏览器,请使用鼠标滚轮)。 图7显示了运行中的应用程序。

图7.滚动文章列表绕补间过渡动画的y轴旋转
轮转文章列表的屏幕截图

诸如文章滚动列表之类的视图是预制的更高级别的Famo.us组件(在本例中为ScrollContainer ),可以将它们组合在一起以方便地创建UI。 下一个示例更详细地探讨了Famo.us的视图和小部件。 现在,足以了解滚动列表由Famo.us Surface的序列集组成。 清单3显示了列表创建代码。

清单3.创建文章滚动列表
function createArticlesList() {
        artListSVC = new ScrollContainer({
            scrollview: {direction: Utility.Direction.Y}
        });
        var lines = [];
        artListSVC.sequenceFrom(lines);

        for (var i in articles)  {
            var surf = new Surface({
                content: '<div class"a-title">' + articles[i].title + '</div>',
                size: [undefined, 50],
                properties: {
                    textAlign: 'left',
                    color: 'black'
                }
            });
            surf.addClass('article-cell');
            surf.addClass('backfaceVisibility');
            surf.artIdx = i;
            surf.pipe(eh);
            lines.push(surf);
        }
        artListSVC.container.addClass('backfaceVisibility');
        artListSVC.container.addClass('borderbox');

    }

清单3中 ,创建了一个名为lines的Famo.us Surface数组。 创建的每个Surface显示一篇developerWorks文章的名称。 创建一个名为artListSVC的Famo.us ScrollContainer ,并使用其sequenceFrom()方法配置带有lines数组的滚动列表。

编程补间过渡

诸如artListSVC的视图也是可渲染的(使用可渲染的树叶管理其自己的内部场景图)。 可以通过一个或多个修饰符对视图进行转换,然后将其添加到上下文的场景图中,如前面的示例所示。 将artListSVC添加到上下文的代码是:

var sm = new StateModifier({align:[0.5, 0.5], 
         origin: [0.5, 0.5]});
mainContext.add(sm).add(artListSVC);

StateModifier是一个随时间(内部,通过Transitionable )维护状态的修改器。 使用补间过渡设置动画时,仅指定开始和结束状态(也称为关键帧 )。 补间过渡会插补中间状态值,并在每个刻度上将它们提供给渲染引擎。 您无需在自己的代码中计算或维护中间状态。

清单4显示了编程补间过渡的代码。

清单4.补间过渡动画
Transitionable.registerMethod('tween', TweenTransition);
 

sm.setTransform(Transform.rotateY(Math.PI), {method: 'tween', 
        curve:'linear', duration:10000},
        function() {
              sm.setTransform(Transform.rotateY(2 * Math.PI), 
               {method: 'tween', duration: 10000,
                curve: 'spring'});
           });

清单4中的代码首先将TweenTransition注册为带有Transitionabletween方法。 然后,使用StateModifiersetTransform()方法添加补间的rotateY变换。 setTransform()方法将转换作为第一个参数,将Transitionable作为第二个参数,并将完成回调函数作为第三个参数。

清单4中 ,第一个动画过渡持续10秒,滚动列表绕y轴以线性速度旋转。 当第一个补间完成时,将触发回调,第二个补间将使用spring并在接下来的10秒钟弹跳的spring曲线。

不必显式注册TweenTransition ,因为如果未为Transitionable指定method属性,则TweenTransition默认使用TweenTransition 。 但是, 清单4展示了如何注册另一种转换方法,例如从Famo.us物理引擎转换。 (Famo.us物理引擎的覆盖范围不在本文的讨论范围之内。)

渲染角度

您指定的渲染透视图(以像素为单位)与从查看者的“相机”到渲染场景的距离相关。 使用Context.setPerspective()设置此值。 较小的值可使观看者在保持相同视场的同时更靠近渲染的对象,并且大致类似于相机上的广角镜。 通过改变视角,可以增强许多动画的外观。 在此示例中,将Perspective设置为500,以获得更显着的效果。

将Famo.us应用于典型的移动应用程序UI

到目前为止,这些示例都像3D渲染库一样操作Famo.us,但2D曲面除外-纯对象动画。 下一个示例确认这种构图和动画样式可以转换为移动UI的构造。

图8显示了常见的移动应用程序布局。 导航栏位于顶部,并且根据UI的状态激活“后退”和“更多”按钮(图8中未显示)。 底部是一个选项卡栏,该选项卡栏由一组切换按钮(可以使用CSS进行样式设置)组成,这些切换按钮用于选择在内容区域中显示的项目。 内容区域位于中间,大小可根据设备大小灵活调整。

图8.在Famo.us中组成移动应用程序UI
典型的移动UI布局的带注释的屏幕截图

通常,该应用包含用户可以进一步浏览的可滚动项目列表。 在这个示例应用程序中,您可以在developerWorks文章列表和开源电影列表之间进行选择。

当用户选择其中一项时,内容区域将更改以显示所选项目。 该项目可能仅在内容区域内打开(即,页眉和页脚仍可见)或占据整个屏幕(遮盖页眉和页脚)。

试用应用

在您的移动浏览器中尝试该应用:

该应用程序启动时,将显示文章列表,如图9所示。

图9. developerWorks文章的应用程序显示
列出文章的示例应用程序屏幕的屏幕截图

如果触摸选项卡栏中的“ 视频”按钮,则会显示开源电影列表,如图10所示。

图10.开源视频的应用程序显示
列出视频的示例应用程序屏幕的屏幕截图

如果您触摸列表中的视频之一,它将在内容区域中加载并播放,如图11所示。

图11.播放电影的应用程序
播放选定视频的应用的屏幕截图

在图11中,请注意,导航栏现在显示一个后退按钮。 如果您触摸该按钮,则会再次显示视频列表。 再次触摸文章以重新显示文章列表。 现在触摸文章名称之一。 该应用程序将加载并显示所选文章,如图12所示。

图12.所选文章的应用程序显示
显示所选文章的应用程序的屏幕截图

使用Famo.us视图和小部件

结合使用Famo.us视图和小部件,可以轻松创建移动应用程序UI。

可以将表面(通常是可渲染对象)和视图组成小部件。 视图可以在托管可渲染对象之间包含复杂的编排和交互逻辑。 使用Famo.us中的事件支持,视图可以接收,处理和发出事件。 小部件本身就是渲染节点,可以作为上下文场景图的叶子添加。 Famo.us附带了一系列现成的视图和小部件:

  • Scrollview控制可渲染Scrollview的顺序列表(在x或y方向上),并允许使用触摸或鼠标在列表中滚动(通常是在一系列表面上)。
  • HeaderFooterLayout管理三个可渲染对象:指定大小的页眉和页脚,以及可变大小的内容区域。 该视图用于布置示例的移动UI。
  • EdgeSwapper是一个容器,用于通过从父级边缘EdgeSwapper滑动多个可渲染对象来管理它们的显示。 示例移动用户界面使用此视图显示两个可滚动列表。
  • ScrollContainer是一个视图,其中包含一个Scrollview和一个用于裁剪ScrollView的显示内容的托管Surface 。 示例移动用户界面在HeaderFooterLayout的内容区域中使用ScrollContainer来显示文章或视频的列表。

示例移动用户界面使用三个小部件:

  • NavigationBar是一个微型应用程序视图,管理标题表面和两个可单击表面的显示,这两个表面分别表示导航条的“后退”和“更多”按钮。 窗口小部件会back并产生more事件。
  • TabBar管理水平或垂直布局的小部件栏。 (默认为切换按钮。)选择了托管窗口小部件时,其相应的ID与select事件一起发出。
  • ToggleButton是一个打开或关闭的按钮,它显示两个托管曲面。

使用可用的视图和小部件,移动UI成为场景图,如图13所示。

图13.移动应用程序UI的场景图
示例应用程序的UI的网屏图说明

尽管上下文仍然位于树的根部,但树的修饰符和叶子不再容易辨认。 每个组成的Famo.us视图都封装了组件的管理详细信息,从而提供了预期的用户交互和行为-消除了对它们进行编码的需要。

要创建移动用户界面,您需要对场景图进行编码; 然后Famo.us引擎对其进行处理并以rAF速率更新DOM:

  1. 创建文章列表-一个Famo.us ScrollContainer其中包含一个管理Surface列表(列表中的单元格)的Scrollview ,每篇文章一个:
    function createArticlesList() {
            artListSVC = new ScrollContainer({
                scrollview: {direction: Utility.Direction.Y}
            });
            var lines = [];
            artListSVC.sequenceFrom(lines);
    
            for (var i in articles)  {
                var surf = new Surface({
                    content: '<div class="a-title">' + articles[i].title + 
                                    '</div><div class="a-desc">' + articles[i].desc + '</div>',
                    size: [undefined, 100],
                    properties: {
                        itemType: 'article',
                        listIndex: i,
                        textAlign: 'left',
                        color: 'black'
                    }
                });
                surf.artIdx = i;
                surf.pipe(eh);
                lines.push(surf);
            }
        }
    function createWebSurface() {
            wb = new Surface(
                );
       
        }

    请注意突出显示的content属性,该属性设置为用于呈现列表中单元格HTML,以及相关CSS类。

    itemTypelistIndex是两个自定义属性,用于标识在click事件处理程序中选择的实际数据项。

  2. 创建视频列表。 (该代码(此处未显示)类似于第1步的代码)。
  3. 创建一个Surface以显示选定的文章:
    function createWebSurface() {
            wb = new Surface(
                );
       
        }
  4. 创建一个Surface以显示选定的视频:
    function createVideoSurface() {
         vs = new VideoSurface(
             {
                 size: [undefined,undefined],
                 autoplay: true
             }
             );
    
    }
  5. 创建NavigationBar小部件并将其添加到标题中:
    function addHeader() {
         nb = new NavigationBar({
             size: [undefined, 75],
             content: 'dW Famo.us',
             moreContent: '',
             backContent: '',
             properties: {
                 lineHeight: '75px'
             }
         });
         layout.header.add(nb);
         eh.subscribe(nb);
         eh.on('back', function() {
             rc.setOptions({
                 inTransition: false,
                 outTransition: true
             });
             if (backTarget !== undefined)
                 rc.show(backTarget);
             setNavbarBack(false, undefined);
         });
    }
  6. 创建EdgeSwapper视图并将其添加到内容区域。 该控制器交换文章列表,视频列表,一篇文章的显示或一部视频的显示:
    function addContent() {
       rc = new EdgeSwapper({
           overlap: false,
           outTransition: false,
           size:[undefined, undefined]
           });
       layout.content.add(rc);
    
    }
  7. 创建选项卡栏并将其添加到页脚中:
    function addFooter() {
        var tb = new TabBar({
        });
        layout.footer.add(tb);
        tb.defineSection(0,{content: 'Articles', onClasses: ['tabbuton'], offClasses: ['tabbutoff']});
        tb.defineSection(1,{content: 'Videos', onClasses: ['tabbuton'], offClasses:['tabbutoff']});
        tb.select(0);
        eh.subscribe(tb);
        eh.on('select', function(but) {
           rc.setOptions({
                inTransition: false,
                outTransition: false
            });
    
          switch (but.id) {
          case 0:
            rc.show(artListSVC);
            break;
          case 1:
            rc.show(vidListSVC);
            break;
          }
          setNavbarBack(false, undefined);
        });
    
    }

    CSS的tabbuton类样式按钮的状态,并tubbutoff风格关闭状态。 如果触摸按钮0 ,则select事件的事件处理程序将显示文章列表;如果触摸按钮1则事件显示将显示视频列表。
  8. 在内容区域中显示文章列表。 为从Scrollview的选择发出的click事件添加事件处理程序:
    function init() {
        rc.show(artListSVC);
        eh.on('click', function(obj) {
                rc.setOptions(
                {
                    inTransition: true,
                    outTransition: false
                });
                var surfaceProps = obj.origin.getProperties();
                if (surfaceProps.itemType === 'article') {
                    wb.setContent('<iframe width="100%" height="100%" src="' + 
                            articles[surfaceProps.listIndex].url + '"></iframe>');
                    rc.show(wb);
                    setNavbarBack(true, artListSVC);
                }
                else
                {   // video
                    vs.setContent(videos[surfaceProps.listIndex].url);
                    rc.show(vs);
                    setNavbarBack(true, vidListSVC);
                }
    
        });
    
    }

现在指定了内存中的场景图,并且所有必需的事件处理程序都已连接好,以供Famo.us引擎处理。

检查在此示例中创建的Famo.us场景图(请参见图13 )。 您可以轻松地对其进行修改以选择和显示其他信息,只需更改数据源和修改样式即可。 这样的修改甚至可以被参数化和自动化。 本质上,您可以为“浏览列表并选择显示项目”移动应用程序的通用类创建UI应用程序模板。 随着时间的推移,可以构建此类应用程序模板的全面集合,以涵盖各种可能的应用程序区域。

结论

创建本机代码移动应用程序很困难。 您不仅需要攀登陡峭的学习曲线,不仅需要多种移动操作系统(以及版本差异),而且还需要在每种平台上攀登不同的编程语言和数百种系统API。 添加专有或定制的工具带,再加上各种构建和部署管道和市场,您最终将获得大量必须跟上和支持的快速发展的技术。 即使您为应用程序准备了现成的样板代码,要在整个移动平台上使其适应新问题,也可能需要数周或数月的编码和调试。

同时,尽管有跨平台的承诺,但用于移动应用程序开发的Web技术仍远远未能交付本机代码UX(直到现在)。 Famo.us框架结合了浏览器优化方面的最新突破以及3D渲染库中的成熟概念,从而为移动Web应用程序提供了高性能,易于使用,高度自动化的UI创建平台。 现在,JavaScript开发人员可以轻松创建可提供与本机代码实现相媲美的用户体验的移动应用程序。

致谢

作者要感谢Famo.us的Andrew De Andrade和Larry Robinson在审阅本文时所提供的帮助。 还有珍妮·费尔德坎普(Jeanne Feldkamp)和史蒂夫·纽科姆(Steve Newcomb)的时间和采访。


翻译自: https://www.ibm.com/developerworks/web/library/wa-famous/index.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值