• This repository has been archived on 02/Dec/2021
  • Stars
    star
    1,034
  • Rank 44,573 (Top 0.9 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 9 years ago
  • Updated almost 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Apple's Auto Layout and Visual Format Language for javascript (using cassowary constraints)

THIS REPOSITORY IS NO LONGER MAINTAINED

Looking for an alternative that is maintained? Please have a look at lume/autolayout.

If you are interested in maintaining this repository (and taking ownership of it), please reach out to me here.

Logo

Build Status view on npm License

AutoLayout.js implements Apple's Auto Layout and Visual Format Language in Javascript. Auto layout is a system which lets you perform lay out using mathematical relationships (constraints). It uses the awesome Cassowary.js library to do the actual constraint resolving and implements Apple's constraint system and Visual Format Language (vfl) on top of that. It supports the Extended VFL syntax, including view-stacks and z-indexing.

var constraints = AutoLayout.VisualFormat.parse([
  'H:|[view1(==view2)]-10-[view2]|',
  'V:|[view1,view2]|'
], {extended: true});
var view = new AutoLayout.View({constraints: constraints});
view.setSize(400, 500);
console.log(view.subViews.view1); // {left: 0, top: 0, width: 195, height: 500}
console.log(view.subViews.view2); // {left: 205, top: 0, width: 195, height: 500}

Layouts can be previewed and debugged using the Visual Format Editor:

Example - click me (click image to open the editor)

Index

Getting started

AutoLayout.js is an abstract library for integrating Auto Layout and VFL into other javascript technologies. It provides a simple API and programming model that you can use to build your own auto layout and VFL solution. A simple example of this is, is using position: absolute; to lay out DOM elements. A more elaborate example of this is the Visual Format Editor, which is built using famo.us and famous-flex. AutoLayout.js is written in ES6 and contains transpiled distribution files.

Installation

Install using npm or bower:

npm install autolayout

bower install autolayout

Include the library in your project:

<head>
  <script type="text/javascript" src="<path-to-autolayout.js>/dist/autolayout.js"></script>
</head>
var AutoLayout = window.AutoLayout;

Or when using a bundler like webpack or browserify, use:

var AutoLayout = require('autolayout.js');

(when using the 'src/' directory, do make sure plugins for transpiling es6 files are installed!)

Using the API

To parse VFL into constraints, use:

try {
  // The VFL can be either a string or an array of strings.
  // strings may also contain '\n' which indicates that a new line of VFL will begin.
  var constraints = AutoLayout.VisualFormat.parse([
    '|-[child(==child2)]-[child2]-|',
    'V:|[child(==child2)]|',
  ]);
} catch (err) {
    console.log('parse error: ' + err.toString());
}

A View is the main entity onto which constraints are added. It uses the cassowary SimplexSolver to add relations and variables. You can set the size of the view and other properties such as spacing. When constraints are added it automatically creates so called "sub-views" for every unique name that is encountered in the constraints. The evaluated size and position of these sub-views can be accessed through the .subViews property.

// Create a view with a set of constraints
var view = new AutoLayout.View({
    constraints: constraints, // initial constraints (optional)
    width: 100,               // initial width (optional)
    height: 200,              // initial height (optional)
    spacing: 10               // spacing size to use (optional, default: 8)
});

// get the size and position of the sub-views
for (var key in view.subViews) {
    console.log(key + ': ' + view.subViews[key]);
    // e.g. {
    //   name: 'child1',
    //   left: 20,
    //   top: 10,
    //   width: 70,
    //   height: 80
    // }
}

By changing the size, the layout is re-evaluated and the subView's are updated:

view.setSize(300, 600);

// get the new size & position of the sub-views
for (var key in view.subViews) {
    console.log(key + ': ' + view.subViews[key]);
}

Instead of using VFL, you can also add constraints directly. The properties are identical to those of NSLayoutConstraint. To constrain view1 to its parent view, use null for view2.

view.addConstraint({
    view1: 'child3',
    attr1: 'width',    // see AutoLayout.Attribute
    relation: 'equ',   // see AutoLayout.Relation
    view2: 'child4',
    attr2: 'width',    // see AutoLayout.Attribute
    constant: 10,
    multiplier: 1
});

API Documentation

The API reference documentation can be found here.

Examples

Extended Visual Format Language (EVFL)

Apple's Visual Format Language prefers good notation over completeness of expressibility. Because of this some useful constraints cannot be expressed by "Standard" VFL. AutoLayout.js defines an extended syntax (superset of VFL) which you opt-in to use. To enable the extended syntax, set option extended to true when parsing the visual format:

var evfl = '|-[view1(==50%)]';
var constraints = AutoLayout.VisualFormat.parse(evfl, {extended: true});

Language features

Proportional size

To make the size proportional to the size of the parent, you can use the following % syntax:

|-[view1(==50%)]    // view1 is 50% the width of the parent (regardless of any spacing)
[view1(>=50%)]      // view1 should always be more than 50% the width of the parent

Operators

Operators can be used to create linear equations of the form: view1.attr1 <relation> view2.attr2 * multiplier + constant.

Syntax:

(view[.{attribute}]['*'|'/'{value}]['+'|'-'{value}])

To, for instance, make the width or height proportional to another view, use:

|-[view1(==view2/2)]-[view2]-|  // view1 is half the width of view2
|-[view1(==view2*4-100)]-[view2]-|  // view1 is four times the width minus 100 of view2

Attributes

In some cases it is useful to for instance make the width equal to the height. To do this you can use the .{attribute} syntax, like this:

|-[view1]-|
V:|-[view1(view1.width)]

You can also combine with operators to for instance enforce a certain aspect ratio:

V:|-[view1(view1.width/3)]

Supported attributes:

.width
.height
.left
.top
.right
.bottom
.centerX
.centerY

Z-Ordering

When sub-views overlap it can be useful to specify the z-ordering for the sub-views:

Z:|[child1][child2]  // child2 is placed in front of child1
Z:|[background]-10-[child1..2]  // child1 and child2 are placed 10 units in-front of background

By default, all sub-views have a z-index of 0. When placed in front of each other, the z-index will be 1 higher than the sub-view it was placed in front of. The z-index of the sub-view can be accessed through the zIndex property:

console.log('zIndex: ' + view.subViews.child2.zIndex);

Equal size spacers / centering

Sometimes you just want to center a view. To do this use the ~ connector:

|~[view1(100)]~|        // view1 has width of 100 and is centered
V:|~(10%)~[view2]~|     // top & bottom spacers have height of 10%

All ~ connectors inside a single line of EVFL are constrained to have the same size. You can also use more than 2 connectors to proportionally align views:

|~[child1(10)]~[child2(20)]~[child3(30)]~|

View stacks

View stacks make it possible to group views into a column or a row. The following example creates a view stack named column which contains three sub-views. The benefit of this is revealed in the second line, in which the stack as a whole is horizontally positioned.

V:|[column:[top(50)][content][bottom(50)]]|
H:|[column]|

View ranges (spread operator)

View ranges make it possible to select multiple views at once and apply rules for them:

//shapes circle1..5:circle
H:[circle1(circle1.height)] // set aspect-ratio for circle1
HV:[circle2..5(circle1)]    // use same width/height for other circles
H:|[circle1]-[circle2]-[circle3]-[circle4]-[circle5]|
V:|~[circle1..5]~|          // center all circles vertically

Multiple views

Similar to 'View ranges', multiple views can be separated using the , character:

H:|[left(top,right)]-[top,bottom]-[right]|
V:|[left,right]|
V:|[top(bottom)]-[bottom]|

Multiple orientations (fill content)

Sometimes you just want to fill a view to its container. With standard VFL you have to write two lines, one for the horizontal orientation and one for vertical:

H:|[background]|
V:|[background]|

With Extended VFL, these can be combined into one line:

HV:|[background]|

When using spacers, you can even use different spacings for horizontal & vertical orientations:

//spacing: [10, 20]
HV:|-[background]-|

Disconnections (right/bottom alignment)

By default, views are interconnected when defined after each other (e.g. [view1][view2][view3]). In some cases it is useful to not interconnect the views, in order to align content to the right or bottom. The following example shows a disconnection causing the content after the disconnect to align to the right-edge:

 // left1..2 are left-aligned, right1..2 are right aligned
      |[left1(100)][left2(300)]->[right1(100)][right2(100)]|
      ^^                       ^^                         ^^
   left1 is                 left2 and                  right2 is
 connected to               right1 are                connected to
  super-view               not connected               super-view

Negative values (overlapping views)

Numbers and percentages can also be negative, which can be useful for overlapping views:

H:|[top,middle,bottom]|
V:|[top(100)]-(-10)-[middle(top)]-(middle/-2)-[bottom]|
Z:|[top][middle][bottom]

Explicit constraint syntax

Constraints can also be expressed explicitly. This can be particularly useful when it is otherwise not possible to express a layout or rule:

C:view1.centerX(view2.centerX)     // view1 is horizontally centered to view2
C:view1.centerX(view2)             // attribute is inferred when omitted (centerX)
C:view1.centerX(view2).bottom(view2.bottom) // chaining syntax
C:view1.height(view2.width*2+10)   // expressions

Comments

Single line comments can be used to explain the VFL or to prevent its execution:

// Enfore aspect ratios
[view1(view1.height/3)] // enfore aspect ratio 1/3
// [view2(view2.height/3)] <-- uncomment to enable

Additional resources

Roadmap

AutoLayout.js is pretty close to feature complete. The existing features have been battle tested in several production environments and can be considered safe for production use.

The following features are still on the todo-list. Any help on making this feature complete is very welcome:

  • Checking for ambigous layout.
  • DOM layouting primitives
  • Remove constraints?
  • Get constraint definitions from View
  • LTR (left to right reading) (Attribute.LEADING & Attribute.TRAILING)
  • Baseline support?

Contribute

If you like this project and want to support it, show some love and give it a star.

If you want to participate in development, drop me a line or just issue a pull request. Also have a look at CONTRIBUTING.

Contact

© 2015-2016 Hein Rutjes

More Repositories

1

react-native-shared-element

Native shared element transition "primitives" for react-native 💫
TypeScript
2,190
star
2

react-native-bundle-visualizer

See what packages are increasing your react-native bundle size 📦
TypeScript
1,466
star
3

react-navigation-shared-element

React Navigation bindings for react-native-shared-element 💫
TypeScript
1,266
star
4

react-native-magic-move

Create magical move transitions between scenes in react-native 🐰🎩✨
JavaScript
973
star
5

firestorter

Use Google Firestore in React with zero effort, using MobX 🤘
TypeScript
378
star
6

famous-flex

Animatable layouts, FlexScrollView & widgets for famo.us.
JavaScript
279
star
7

kiwi.js

Fast TypeScript implementation of the Cassowary constraint solving algorithm 🖖
JavaScript
250
star
8

react-navigation-magic-move

Bindings for using react-navigation with react-native-magic-move 🐰🎩✨
JavaScript
135
star
9

react-tag-cloud

Create beautiful tag/word clouds using React ☁️
TypeScript
118
star
10

famous-map

Map integration for famo.us (Google Maps, Leaflet, Open Layers 3 & Mapbox GL)
JavaScript
109
star
11

visualformat-editor

Editor & previewer for Apple's Visual Format Language (built with autolayout.js)
JavaScript
90
star
12

node-web-bluetooth

Web Bluetooth API and interactive device picker for node.js
JavaScript
75
star
13

react-navigation-shared-element-demo

A simple app that demonstrates how to use react-navigation-shared-element in react-native
JavaScript
65
star
14

famous-autolayout

Apple's Auto Layout and Visual Format language for famo.us
JavaScript
55
star
15

famous-flex-chat

Chat-demo for famo.us using true-size chat bubbles, snap to bottom, sticky headers & pull-to-refresh
JavaScript
52
star
16

pnglib-es6

Create png images in pure javascript (modern & fast ES6 version using typed Arrays)
JavaScript
45
star
17

famous-boxlayout

Layout-view for quickly setting margins or creating flexible layouts
JavaScript
28
star
18

famous-animatedIcon

Material design'ish button-animation using famo.us
JavaScript
27
star
19

famous-flex-datepicker

Date/time picker demo for famo.us
JavaScript
26
star
20

rtfToHtml

Parse RTF and write output as an HTML file (written specifically for InDesign generated RTF, but works for any source)
JavaScript
21
star
21

android-tv-browser-autolaunch

Android TV App (react-native) that auto-launches on boot and shows a browser with a hard-coded URL
Objective-C
20
star
22

famous-sizeconstraint

SizeConstraint makes it possible to set the scale, padding, max-size, min-size and aspect-ratio for famo.us renderables
JavaScript
20
star
23

famous-kenburnscontainer

Famo.us view for performing ken-burns style zooming and panning
JavaScript
19
star
24

famous-listview

famous-listview extends famo.us ScrollContainer with insert/remove animations, selection (single/multiple) and support for a placeholder.
JavaScript
18
star
25

famous-lagometer

Lagometer for famo.us showing the FPS, animation-frames times and script times
JavaScript
18
star
26

famous-bkimagesurface

Drop-in replacement for ImageSurface supporting AspectFit & AspectFill
JavaScript
18
star
27

famous-flex-tabbar

TabBar widget demo for famo.us
JavaScript
18
star
28

famous-flex-tabbarcontroller

TabBarController widget demo for famo.us
JavaScript
17
star
29

famous-white-tile-firebase

Popular white tile (piano tiles) game implemention using famo.us and firebase
JavaScript
17
star
30

famous-refresh-loader

Spinning pull to refresh loader for famo.us
JavaScript
15
star
31

famous-autosizetextarea

Auto-sizing TextareaSurface for famo.us
JavaScript
14
star
32

famous-components

Overview of famo.us components
14
star
33

famous-flex-demo

Demo for showcasing famous-flex layout technology
JavaScript
9
star
34

react-native-magic-move-presentation

Presentation App/Slides for the react-native-magic-move presentation given at ReactEurope 2019
JavaScript
9
star
35

react-native-clipped

Clipping effects and animations for react-native 🍠🥒🍕
JavaScript
7
star
36

famous-flex-tablelayout

iOS inspired table-layout for famo.us
JavaScript
7
star
37

expo-firebase-demo

Firebase Demo running on Expo
TypeScript
6
star
38

famous-white-tile

Popular white tile (piano tiles) game implemention using famo.us
JavaScript
5
star
39

famous-autofontsizesurface

Surface that automatically scales the font-size based on the content.
JavaScript
5
star
40

famous-flex-animationcontroller

Animating from one famo.us view to another in awesome ways
JavaScript
5
star
41

ttvflash

TTV Flash Presentatie App
JavaScript
4
star
42

famous-Starterkit

Starterkit for famo.us (app + web) containing examples, instructions & best practises
JavaScript
4
star
43

famous-resizableImage

Resizable image for famo.us
JavaScript
4
star
44

top2000-stemlijst

Importeer jouw Top 2000 stemlijst eenvoudig naar Spotify, Apple Music of Deezer
TypeScript
4
star
45

firestore-cms

A free, flexible and easy to use CMS for Google Firestore 🎉
JavaScript
4
star
46

famous-sizemodifier

Deprecated - Use famous-sizeconstraint instead
JavaScript
3
star
47

famous-resources

Unofficial list of famo.us resources
2
star
48

expo-git-import-main

TypeScript
2
star
49

wkwebview-crash

Project to intentionally crash WkWebView for testing purposes
Objective-C
2
star
50

famous-lib-tester

Project for testing whether my libraries and famo.us can be build successfully using webpack, browserify, etc...
JavaScript
1
star
51

famous-test-positionabsolute

Test for absolute positioning issue when showing keyboard on mobile (iOS & android)
JavaScript
1
star
52

expo-av-9596-repro

JavaScript
1
star
53

famous-zindex

JavaScript
1
star
54

famous-bling

View templates (with animations) to jumpstart your project or for production use
JavaScript
1
star
55

famous-flex-scrollview-linking

Demo for showcasing FlexScrollView leading & trailing scrollview linking
1
star
56

ijzerenhein-website

My personal public website
JavaScript
1
star
57

famous-physics-playground

Playground for experimenting with physics based animation effects
JavaScript
1
star
58

contributors-code

Life as an open source contributor
1
star
59

expo-av-music-control

Java
1
star
60

famous-flex-truesize-layoutcontroller-demo

JavaScript
1
star
61

scrollview.js

Lightweight & fast javascript scrollview, look no further
JavaScript
1
star
62

famous-playground

General purpose playground repo for famo.us
JavaScript
1
star