Animatable layouts, FlexScrollView & widgets for famo.us.
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.
famous-flex was written for the v0.3.x API of famo.us. The new mixed-mode API of famo.us is drastically different and famous-flex therefore needs to be ported to the new API and engine. Some parts will need to be upgraded while others will need to be rewritten from scratch. Also, BEST integration needs to be added. A new branch called 'mixed-mode' will be created on which all mixed-mode development will take place, starting with a LayoutController and the core layouts. After that the Scrolling support shall be added and finally the widgets.
In order to make this happen, community contributions would be very welcome to speed up the process. If you want to help, please drop me a line at [email protected]. Also, donations are very welcome and will allow me to spent more time on migrating to mixed-mode and on new famous-flex features. If you want to donate, click here.
- famous-flex-demo (source)
- AnimationController demo (source)
- Chat demo (source)
- DatePicker demo (source)
- TabBar demo (source)
- TabBarController demo (source)
- LayoutController
- AnimationController
- ScrollController
- FlexScrollView
- DatePicker
- TabBar
- TabBarController
- ProportionalLayout
- HeaderFooterLayout
- NavBarLayout
- TabBarLayout
- ListLayout (scrollable)
- CollectionLayout (scrollable)
- WheelLayout (scrollable)
Install using bower or npm:
bower install famous-flex
npm install famous-flex
LayoutController is a view that lays out renderables based on:
- a layout-function
- a data-source containing renderables
- optional layout-options
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.
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:
- A resize occurs
- An option is changed on the layout-controller
- When the content is scrolled
The data-source contains the renderables that are to be layed-out. It can be one of three things:
- An
Array
- A
ViewSequence
- An
Object
with key/value pairs
In case of an Array
or 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 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:
- Create a LayoutHelper (see LayoutDockHelper for an example).
- Implement the
parse
function on the LayoutHelper. - Register the helper using
LayoutUtility.registerHelper
.
Layout helpers are special classes that simplify writing layout functions.
Helper | Literal | Description |
---|---|---|
LayoutDockHelper | dock |
Layout renderables using docking semantics. |
Layout | DataSource | Scrollable | Description |
---|---|---|---|
ProportionalLayout | ViewSequence / Array | No | Lays out renderables sequentially and sizes them proportionally. |
HeaderFooterLayout | Id-based | No | Layout containing a top-header, bottom- footer and content. |
NavBarLayout | Id-based | No | Layout containing one or more left and right items and a title. |
TabBarLayout | Id-based | No | Tab-bar layout. |
Scrollable layouts: | |||
ListLayout | ViewSequence / Array | Yes | List layout with margins, spacing and optionally sticky headers. |
CollectionLayout | ViewSequence / Array | Yes | Lays out renderables in a grid with a specific width & height. |
WheelLayout | ViewSequence / Array | Yes | Lays out renderables in a wheel (slot-machine) formation. |
Class | Description |
---|---|
LayoutController | Lays out renderables and optionally animates between layout states. |
AnimationController | Animating between famo.us views in awesome ways. |
ScrollController | Scrollable LayoutController (base class for FlexScrollView). |
FlexScrollView | Flexible scroll-view with pull-to-refresh, margins & spacing and more good stuff. |
DatePicker | Date/time picker wheel. |
TabBar | TabBar widget. |
TabBarController | TabBarController widget. |
LayoutContext | Context used for writing layout-functions. |
LayoutUtility | Utility class containing helper functions. |
VirtualViewSequence | Infinite view-sequence which uses a factory delegate to create renderables. |
Famous-flex is still in its infancy. I am commited in creating a first-class layout-solution for famo.us that is as performant, pluggable and awesome as can be. But to do this, I need your support and feedback. Let me know which of features below are most important to you, by leaving a comment in the corresponding issue.
- AutoLayout (Cassowary constraints)
- Drag & drop (Drag & drop renderables in a layout)
- New widgets (Suggestions for new widgets)
- New Layouts (Suggestions for new layouts)
If you like this project and want to support it, show some love and give it a star.
- @IjzerenHein
- http://www.gloey.nl
- [email protected] (for hire)
© 2014 - 2015 Hein Rutjes