Famo.us is an open source JavaScript framework for building high-performance mobile Web and hybrid mobile apps. The framework gets its speed and sizzle by replacing the browser's slow, DOM-based rendering mechanism with its own rendering engine and by tapping the GPU acceleration provided by CSS3's 3D transformation functions -- no plug-ins or native code required.
In the lore of Famo.us, the origin of the framework was the original team's struggle with HTML5, CSS3, and the DOM (Document Object Model). According to architect Dave Valdman, writing on the Famo.us site, "We wondered if we could move a square <div> at 60 FPS entirely in JavaScript without relying on CSS3 keyframe animations... then we built a framework around it." Valdman now adds one comment to that for context: "Animation is our humble roots, but our library has matured into much more."
To introduce you to the way Famo.us works, I've captured and explained a series of screens from the Famo.us tutorials, demos, and samples. When the company can clear up its backlog of beta applicants (more than 80,000 at the time of my visit) and fix the issues that inevitably surface after a developer product launch, you'll be able to try the framework yourself.
Hello, Famo.us
The "Hello Famo.us" lesson creates a device emulator (shown here as an iPhone), then adds a background surface in color #FA5C4F, three slide images, and onClick logic to the slide surface to create a simple slideshow app. The most impressive part of the demo is that the preview updates instantly as you change the code online.
Note the settings near the top of the code. Transition animations can follow standard or custom easing curves or physical simulations between endpoints, vary opacity, and change the translation, rotation, origin, and size of surfaces.
Displaying content
The first actual lesson in Famo.us 101 covers how to display and style content in Famo.us using JavaScript, HTML, and CSS. You'll notice that styling surfaces in Famo.us is just like writing CSS, except that the properties are written using camelCase instead of dashes. That's because the standard CSS property names with dashes are not valid JavaScript -- the dash is interpreted as a minus sign or subtraction operator. Ultimately, these styles become their equivalent CSS properties.
Note the use of require statements in the code above. The require statement is not standard JavaScript, but comes from the RequireJS framework, a JavaScript file and module loader. Famo.us expects to eventually eliminate the use of RequireJS for its own framework.
Transforms
The second lesson in Famo.us 101 starts by covering translations and state modifiers. In this example the createSurface function defines the 100-by-100-pixel square in the upper left with the text "surface," and the createModifiedSurface function creates the other square with the text "modified surface" and translates it 150 pixels to the right and 100 pixels down.
Note that the translation parameters include values for the x, y, and z axes. Also note that chained modifiers apply from right to left: mainContext.add(stateModifier).add(modifiedSurface) means that modifiedSurface has stateModifier, defined as Transform.translate(150, 100, 0), applied before it is added to mainContext and displayed.
Famo.us uses matrix3d WebKit transforms on <div> elements with absolute positions rather than using a conventional nested DOM tree in which child elements are positioned relative to their parent elements. Famo.us gains performance by using the hardware-accelerated matrix3d WebKit transforms and avoiding the relatively slow layout flow calculations of a typical HTML5 page.
Overall, the way Famo.us does transforms and rendering feels a lot more like the way console games do their graphics than the way Web browsers normally work.
Rotations
Lesson 2 goes on to explain chaining modifiers and applying rotations. As you probably remember from your high school analytic geometry, a translation followed by a rotation will give you different results than a rotation followed by a translation.
As discussed earlier, chaining is applied right to left, so mainContext.add(translateMod).add(rotateMod).add(surface) adds the surface to the main context, rotates it Pi/4 radians (45 degrees), and translates it down 100 pixels and to the right 100 pixels.
Reversing the order -- mainContext.add(rotateMod).add(translateMod).add(surface), for example -- would give us a rectangle cut off at the left:
Famo.us Render Tree
As we discussed earlier, Famo.us uses matrix3d WebKit transforms on <div> elements with absolute positions rather than using a conventional nested DOM tree in which child elements are positioned relative to their parent elements.
Famo.us keeps the structure of HTML in the JavaScript Render Tree and renders to absolutely positioned <div> elements, creating a flat HTML DOM that doesn't require any flow calculations for a redraw. The HTML <body> tag corresponds to a Famo.us Context, more or less. The Context corresponds to an isolated drawing universe. You need at least one Context, but you could have many in the same <body>.
The Render Tree has two types of nodes: renderables, such as a Surface, and modifiers, which are responsible for the layout and visibility of the Render Tree below them. Modifiers can be chained, as I mentioned earlier.
Views
In Famo.us, views are encapsulations of groups of renderables and modifiers that you wish to hide from the master Render Tree. Views are typically what a Unix UI developer would call a widget, but implemented as a Famo.us RenderNode paired with an input EventHandler and an output EventHandler. The views in the Famous Example repository as of this writing are Deck, EdgeSwapper, GridLayout, HeaderFooterLayout, RenderController, Scrollview, and SequentialLayout. The expectation is that you'll subclass views to extend and customize them into your own widgets, or write your own renderable items from more basic components.
Physics transitions
Famo.us has a physics engine that can do a lot of game-like simulation, the least of which is to make animations bounce in a realistic-feeling way by using a spring model to guide the transitions. In this lesson, the red square drops from the top, overshoots the final position, and bounces three times in the span of about two seconds. If you adjust the period and dampingRatio of the spring transform, the bouncing speed and decay curve change. You can adjust the numbers and immediately see the new animation behavior.
Famo.us has plans to surface visual controls for animations as part of the platform in the future, so designers can achieve the behavior they want without involving a software engineer in tweaking the simulation parameters. I have seen an unreleased prototype of one example of this running on an iPhone.
Events
Famo.us has an EventHandler API that allows a user to broadcast, listen for, pipe to, and subscribe from events. Event handlers can broadcast with the emit or trigger method. Downstream handlers can listen for the event with the on method.
Event handlers can pipe events to downstream event handlers, and subscribe to events from upstream event handlers. Pipes can be chained. In general, the best practice is to use a subscription pattern, especially when listening on DOM events. Note that this explicit piping stands in contrast to the implicit event bubbling in the HTML DOM.
The Famo.us View base class, and therefore every derived view and widget, includes both input and output event handlers. The event library comes with convenience modules for conditionally processing events, including event filtering, mapping, and arbitration.
Positioning
Famo.us does all positioning using transforms, which are basically four-by-four matrices applied to surfaces with absolute positions. As I mentioned earlier, transforms can perform translation and rotation. In addition, they can scale a surface, size it, and set its origin. The matrix multiplications that apply transforms to surfaces are straightforward, which is how the game-like Famo.us engine can render faster than a Web browser would calculate and display all the flow required for deeply nested HTML documents.
Famo.us Toolbelt
When you are admitted to Famo.us University, you can download any of the Famo.us demo and tutorial projects. In order to work with the supplied projects on your own machine and to create new projects, you'll want to install the Famo.us Toolbelt. This is basically a set of Yeoman generator and Grunt scripts to create projects and views, run a local development Web server, and package your project for distribution. You'll need Git, Node.js, Grunt, and Bower. On a Mac, you can install Node.js using Homebrew, and you can install Grunt and Bower from the Node package manager Npm.
Demos
As of this writing, 15 demos are available from the Famo.us site. In all cases, you can play with the demo online and download the project zip file.
Hello, Famo.us?
Famo.us is currently being beta tested by some 5,000 developers, with rollout to 500 new beta testers each day. The company expects the beta to be fully open by May 19. Meanwhile, the Famo.us Docs (basically formatted comments from the framework) and Guides (actual tutorial material) are available to all. The installation instructions, Demos, and Famo.us University lessons, however, require a login password.
Famo.us promises significantly better performance than standard mobile websites, it's more flexible for UI development than HTML5, and it's easier for developers to use than native code. But as I hope you've seen from this walk-through, the framework currently looks and feels more like an animation or game system than a conventional Web toolkit.
The company plans to make the product much easier to learn and use in the future -- even for designers who don't know JavaScript. But if you want to "be Famo.us" right now, you would be well served by serious JavaScript experience or a game development background.