Home

Awesome

Logo famous-flex

Animatable layouts, FlexScrollView & widgets for famo.us.

Screenshot

Above anything, famous-flex is a concept in which renderables are seperated from how they are layed-out. This makes it possible to change layouts on the fly and animate the renderables from one layout to another. For instance, you can layout a collection of renderables using a CollectionLayout, and change that into a ListLayout. When using flow-mode the renderables will smoothly transition from the old state to the new state using physics, particles and springs.

Demos

Getting started

Core concepts

Views / widgets

Layouts

Resources

Installation

Install using bower or npm:

bower install famous-flex

npm install famous-flex

LayoutController

LayoutController is a view that lays out renderables based on:

Example of laying out renderables using a CollectionLayout:

var LayoutController = require('famous-flex/LayoutController');
var CollectionLayout = require('famous-flex/layouts/CollectionLayout'); // import standard layout

// create collection-layout
var layoutController = new LayoutController({
    layout: CollectionLayout,
    layoutOptions: {
        itemSize: [100, 100],
        gutter: [20, 20],
        justify: true
    },
    flow: true,    // smoothly animates renderables when changing the layout
    direction: 1,  // 0 = X, 1 = Y, undefined = use default from selected layout-function
    dataSource: [
        new Surface({content: 'surface1'}),
        new Surface({content: 'surface2'}),
        new Surface({content: 'surface3'})
    ]
});
this.add(layoutController); // add layout-controller to the render-tree

When the flow option is enabled, renderables are animated smoothly between layout states.

Layout function

A layout is represented as a Function, which takes a context argument and an optional options argument. The purpose of the function is to lay-out the renderables in the data-source by calling context.set() on a renderable. The renderables can be enumerated by calling context.next(), context.prev() or by using the id of the renderable.

Famous-flex comes shipped with various standard layouts, but it is also very easy to create your own layout-functions. View LayoutContext for more details on creating your own layout-functions.

/**
 * @param {LayoutContext} context Context used for enumerating renderables and setting the layout
 * @param {Object} [options] additional layout-options that are passed to the function
 */
function LayoutFunction(context, options) {

    // simple layout-function that lays out renderables from top to bottom
    var node = context.next();
    var y = 0;
    while (node) {
        context.set(node, {
            size: [context.size[0], 100],
            translate: [0, y, 0]
        });
        y += 100;
        node = context.next();
    }
};

For optimal performance, the layout function is only executed when:

Datasource

The data-source contains the renderables that are to be layed-out. It can be one of three things:

In case of an Array or a ViewSequence, use context.next() in your layout-function to enumerate all the renderables in the data-source:

var layoutController = new LayoutController({
    layout: function (context, options) {
        var y = 0;
        var node = context.next();
        while (node) {
            context.set(node, {
                size: [context.size[0], 100],
                translate: [0, y, 0]
            });
            y += 100;
            node = context.next();
        }
    },
    dataSource: [
        new Surface({content: 'surface1'}),
        new Surface({content: 'surface2'}),
        new Surface({content: 'surface3'})
    ]
});

Sometimes it is easier to identify renderables by an id, rather than a sequence. In that case use context.get() or directly pass the data-source id to the context.set() function:

var layoutController = new LayoutController({
    layout: function (context, options) {
        context.set('one', {
            size: [100, 100],
            translate: [0, 0, 0]
        });
        context.set('two', {
            size: [100, 100],
            translate: [100, 0, 0]
        });
        context.set('three', {
            size: [100, 100],
            translate: [200, 0, 0]
        });
    },
    dataSource: {
        'one': new Surface({content: 'one'}),
        'two': new Surface({content: 'two'}),
        'three': new Surface({content: 'three'})
    }
});

Layout literals

Layout literals are objects which describe layouts through a definition rather than a function. The following example describes the use of a layout literal using dock semantics (see LayoutDockHelper):

var layoutController = new LayoutController({
    layout: {dock: [
        ['top', 'header', 50],
        ['bottom', 'footer', 50],
        ['fill', 'content']
    ]},
    dataSource: {
        header: new Surface({content: 'Header'}),
        footer: new Surface({content: 'Footer'}),
        content: new Surface({content: 'Content'})
    }
});

Layout literals are implemented through LayoutHelpers. To create your own layout literals, perform the following steps:

Layout helpers

Layout helpers are special classes that simplify writing layout functions.

HelperLiteralDescription
LayoutDockHelperdockLayout renderables using docking semantics.

Standard layouts

LayoutDataSourceScrollableDescription
ProportionalLayoutLinkedListViewSequence / ArrayNoLays out renderables sequentially and sizes them proportionally.
HeaderFooterLayoutId-basedNoLayout containing a top-header, bottom- footer and content.
NavBarLayoutId-basedNoLayout containing one or more left and right items and a title.
TabBarLayoutId-basedNoTab-bar layout.
Scrollable layouts:
ListLayoutLinkedListViewSequence / ArrayYesList layout with margins, spacing and optionally sticky headers.
CollectionLayoutLinkedListViewSequence / ArrayYesLays out renderables in a grid with a specific width & height.
WheelLayoutLinkedListViewSequence / ArrayYesLays out renderables in a wheel (slot-machine) formation.
CoverLayoutLinkedListViewSequence / ArrayYesLays out renderables in a wheel (slot-machine) formation.

Documentation

ClassDescription
LayoutControllerLays out renderables and optionally animates between layout states.
AnimationControllerAnimating between famo.us views in awesome ways.
ScrollControllerScrollable LayoutController (base class for FlexScrollView).
FlexScrollViewFlexible scroll-view with pull-to-refresh, margins & spacing and more good stuff.
DatePickerDate/time picker wheel.
TabBarTabBar widget.
TabBarControllerTabBarController widget.
LayoutContextContext used for writing layout-functions.
LayoutUtilityUtility class containing helper functions.
VirtualViewSequenceInfinite view-sequence which uses a factory delegate to create renderables.
LinkedListViewSequenceLinked-list based View-sequence which resolves various issues with the stock famo.us ViewSequence.

Contribute

If you like this project and want to support it, show some love and give it a star. Any donations are also very welcome and appreciated. To donate click here.

© 2014 - 2016 Hein Rutjes