- Notifications
You must be signed in to change notification settings - Fork62
Apple's Auto Layout and Visual Format Language for javascript (using cassowary constraints)
License
IjzerenHein/autolayout.js
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Looking for an alternative that is maintained? Please have a look atlume/autolayout.
If you are interested in maintaining this repository (and taking ownership of it), please reach out to mehere.
AutoLayout.js implements Apple'sAuto Layout andVisual Format Language in Javascript. Auto layout is a system which lets you perform lay out using mathematical relationships (constraints). It uses the awesomeCassowary.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 theExtended VFL syntax, including view-stacks and z-indexing.
varconstraints=AutoLayout.VisualFormat.parse(['H:|[view1(==view2)]-10-[view2]|','V:|[view1,view2]|'],{extended:true});varview=newAutoLayout.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 theVisual Format Editor:
(click image to open the editor)
- THIS REPOSITORY IS NO LONGER MAINTAINED
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 usingposition: absolute;
tolay out DOM elements. A more elaborate example of this is theVisual Format Editor, which is built usingfamo.us andfamous-flex. AutoLayout.js is written in ES6 and contains transpiled distribution files.
Install using npm or bower:
npm install autolayoutbower install autolayout
Include the library in your project:
<head><scripttype="text/javascript"src="<path-to-autolayout.js>/dist/autolayout.js"></script></head>
varAutoLayout=window.AutoLayout;
Or when using a bundler like webpack or browserify, use:
varAutoLayout=require('autolayout.js');
(when using the 'src/' directory, do make sure plugins for transpiling es6 files are installed!)
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.varconstraints=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 addrelations 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 constraintsvarview=newAutoLayout.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-viewsfor(varkeyinview.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-viewsfor(varkeyinview.subViews){console.log(key+': '+view.subViews[key]);}
Instead of using VFL, you can also add constraints directly.The properties are identical to those ofNSLayoutConstraint.To constrain view1 to its parent view, usenull 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});
The API reference documentation can be found here.
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 optionextended
totrue
when parsing the visual format:
varevfl='|-[view1(==50%)]';varconstraints=AutoLayout.VisualFormat.parse(evfl,{extended:true});
- Proportional size (
|-[view1(==50%)]
) - Operators (
|-[view1(==view2/2-10)]-[view2]-|
) - Attributes (
V:|[view2(view1.width)]
) - Z-ordering (
Z:|-[view1][view2]
) - Equal size spacers/centering(
|~[center(100)]~|
) - View stacks (
V:|[column:[header(50)][content][footer(50)]]|
) - View ranges (spread operator) (
H:[view1..8(10)]|
) - Multiple views (
Z:|[background][text1,text2,text3]|
) - Multiple orientations (
HV:|[background]|
) - Disconnections (right/bottom alignment) (
|[view1(200)]->[view2(100)]|
) - Negative values (overlapping views) (
|[view1]-(-10)-[view2]|
) - Explicit constraint syntax (
C:view1.centerX(view2.centerX)
) - Comments (
[view1(view1.height/3)] // enfore aspect ratio 1/3
)
To make the size proportional to thesize 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 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 toanother 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
In some cases it is useful to for instance make thewidth equal to the height. To do this you canuse the.{attribute}
syntax, like this:
|-[view1]-|V:|-[view1(view1.width)]
You can also combine with operators to for instance enforce a certainaspect ratio:
V:|-[view1(view1.width/3)]
Supported attributes:
.width.height.left.top.right.bottom.centerX.centerY
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 child1Z:|[background]-10-[child1..2] // child1 and child2 are placed 10 units in-front of background
By default, all sub-views have a z-index of0
. When placed in front of each other, the z-indexwill be1
higher than the sub-view it was placed in front of. The z-index of the sub-view canbe accessed through thezIndex
property:
console.log('zIndex: ' + view.subViews.child2.zIndex);
Sometimes you just want to center a view. To do this use the~
connector:
|~[view1(100)]~| // view1 has width of 100 and is centeredV:|~(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 make it possible to group views into a column or a row.The following example creates a view stack namedcolumn
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 make it possible to select multiple views at once and apply rules for them:
//shapes circle1..5:circleH:[circle1(circle1.height)] // set aspect-ratio for circle1HV:[circle2..5(circle1)] // use same width/height for other circlesH:|[circle1]-[circle2]-[circle3]-[circle4]-[circle5]|V:|~[circle1..5]~| // center all circles vertically
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]|
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]-|
By default, views are interconnected when defined after each other (e.g.[view1][view2][view3]
). In some casesit is useful to not interconnect the views, in order to align content to the right or bottom. The followingexample 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
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]
Constraints can also be expressed explicitly. This can be particularly usefulwhen it is otherwise not possible to express a layout or rule:
C:view1.centerX(view2.centerX) // view1 is horizontally centered to view2C:view1.centerX(view2) // attribute is inferred when omitted (centerX)C:view1.centerX(view2).bottom(view2.bottom) // chaining syntaxC:view1.height(view2.width*2+10) // expressions
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
- Apple's Auto Layout
- Visual Format Language
- Cassowary.js
- Kiwi.js (Fast TypeScript re-implementation of cassowary constraint solver)
- Overconstrained
- Visual Format Editor
- famous-autolayout
- famous-flex
AutoLayout.js is pretty close to feature complete. The existing features havebeen 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 thisfeature 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?
If you like this project and want to support it, show some loveand 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 atCONTRIBUTING.
- @IjzerenHein
- hrutjes@gmail.com (for hire)
© 2015-2016 Hein Rutjes
About
Apple's Auto Layout and Visual Format Language for javascript (using cassowary constraints)
Topics
Resources
License
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors6
Uh oh!
There was an error while loading.Please reload this page.