[UPDATE] Famo.us 官方已捨棄此模組,詳情請看官方 Github
Famo.us 原始碼可以在官方的 github 下載
如果你已經可以進入 Famo.us University,那這裡或許可以跳過。
基本使用
Famo.us 是基於 AMD 的架構來撰寫,且搭配使用 require.js,所以稍微了解一下這兩個東西會比較容易上手。
安裝
你可以從官方的 github 把專案抓下來直接使用,也可以用 nodeJS 來安裝,這裡介紹一下 nodeJS 的安裝方法,或者是參考官方的 Install
sudo npm install -g yo grunt-cli bower generator-famous
mkdir newProject && cd newProject
yo famous
_-----_
| |
|--(o)--| .--------------------------.
`---------´ | Welcome to Yeoman, |
( _´U`_ ) | ladies and gentlemen! |
/___A___\ '__________________________'
| ~ |
__'.___.'__
´ ` |° ´ Y `
You're using the fantastic Famo.us generator.
[?] Your project name: (newProject) // 輸入專案的名稱(不打也行
[?] Your project description: e.g. Seed project to get started with Famo.us // 輸入專案的描述(不打也行
[?] Would you mind telling me your username on Github? // 輸入你的 github 名稱(不打也行
跑了一陣子之後,他會把需要的東西全部安裝完畢,最後用 grunt serve
來啟動服務。他會啟動瀏覽器連線到 localhost:1337
,同時支援 livereload,所以你可以直接修改 js 檔案來看到效果。
檔案會放在 app/src/main.js
裡面。
顯示元件
建構一個畫面,我們需要 Engine
, Surface
這兩個模組,所以,這樣就能夠在畫面上產生一段文字
define(function(require, export, module) {
var Engine = require('famo/core/Engine');
var Surface = require('fame/core/Surface');
var mainContext = Engine.createContext();
var surf = new Surface({
// 這個 size 代表這個 Surface 是 200x200 的正方形
size: [200, 200],
content: "Hello World"
});
mainContext.add(surf);
});
然後,我們可以利用 Modifier
這個模組,來修改或是製作這個 Surface
的效果
define(function(require, exports, module) {
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Modifier = require('famous/core/Modifier');
var Transform = require('famous/core/Transform');
var mainContext = Engine.createContext();
var surf = new Surface({
// 這個 size 代表這個 Surface 是 200x200 的正方形
size: [200, 200],
content: "Hello World"
});
var mod = new Modifier({
// transform 表示套用一組 Tramsform 模組的效果
transform: Transform.translate(100, 0, 0),
// origin 表示把底下的元素放在螢幕某個位置,0.5, 0.5 代表正中央
origin: [0.5, 0.5]
});
mainContext.add(mod).add(surf);
});
Surface 核心模組
它是屬於核心模組之一,原始碼在 core/Surface.js
可以查看。預設所使用的 Markup 是 <div>
元素,預設的類別樣式名稱為 famous-surface
,這兩項是無法被修改的。可以傳入的屬性有,
properties
用來設定 CSS 樣式content
傳入的內容,允許使用 HTMLclasses
傳入類別樣式名稱,必須使用陣列size
傳入元件的尺寸,陣列,規格為[ width, height ]
,必須單純為數字(單位 px,比較特別的是,他可以傳入undefined
這個關鍵字,代表意義是100%
Modifier 核心模組
核心之一,原始碼在 core/Modifier.js
可以查看。它可以當作是一種效果的套用(或是下層元素的濾鏡)來看,樹狀結構以上面的例子來看,會長成這樣
mainContent
|
Modifier
|
Surface
這一個 Modifier 並不會產生任何的元素,相反的,它會是一種 CSS Style 屬性,_套用_在 Surface 的元素上面,以 HTML Mackup 來解釋就是這樣,
<div class="famous-surface" style="/* Modifier 會在這裡發生 */"></div>
它可以傳入的屬性有,
transform
這個傳入值必須要是Transform
模組opacity
這個傳入值是透明度,範圍在 0 ~ 1origin
這是代表我要將所屬元素設定在畫面的哪個位置,它是一個陣列[ 垂直位置, 水平位置 ]
size
這個尺寸跟Surface
的尺寸設定相同,但是會覆蓋掉Surface
所設定的尺寸
origin
是一種九宮格的形式,所代表的相對位置如下表,
| 左 | 中 | 右 |
--- | ---- | ---- | ---- |
上 | [0, 0]
| [0.5, 0]
| [1, 0]
|
中 | [0, 0.5]
| [0.5, 0.5]
| [1, 0.5]
|
下 | [0, 1]
| [0.5, 1]
| [1, 1]
|
相關模組
相同於核心的 Surface
與 Modifier
這兩個模組,Famous 對他有個別擴展兩組模組,分別是,
Surface 模組
surfaces/CanvasSurface
surfaces/ContainerSurface
surfaces/ImageSurface
surfaces/InputSurface
surfaces/VideoSurface
以上這幾種模組都是由 core/Surface
擴展而來,唯一的差異性是這些模組所使用的 HTML Tag 不盡相同,
模組 | 使用的 HTML Tag | 可傳入屬性設定 |
---|---|---|
Surface | <div> |
同上述 Surface 部分 |
CanvasSurface | <canvas> |
canvasSize 為一陣列 [ width, height ] |
ContainerSurface | <div> |
同 Surface |
ImageSurface | <img> |
content 必須為圖片的 URL |
InputSurface | <input> |
placeholder , value , type , name ,同時 content 是無效的 |
VideoSurface | <video> |
同 Surface 但是多了 autoplay 是布林值 |
在此必須把 ContainerSurface
特別提出來說明,他與 Surface
雷同,但是在 HTML Markup 的結構上並不太一樣,簡單來說,它可以把很多的 Surface
給包(Group)起來,舉例來說,
define(function(require, exports, module) {
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Modifier = require('famous/core/Modifier');
var Transform = require('famous/core/Transform');
var ContainerSurface = require('famous/surfaces/ContainerSurface');
var mainContainer = Engine.createContext();
var container = new ContainerSurface();
var surface, modifier;
for (var i = 0; i < 5; i++) {
surface = new Surface({
size: [100, 100],
content: 'box '+ i
});
modifier = new Modifier({
transform: Transform.translate( i * 110, 0, 0 )
});
container.add(modifier).add(surface);
}
mainContainer.add(container);
});
這樣的方式所產出的 HTML Markup 會類似這樣(底下結構已簡化,
<div class="famous-surface">
<div class="famous-group famous-container-group">
<div class="famous-surface">test</div>
<div class="famous-surface">test</div>
<div class="famous-surface">test</div>
<div class="famous-surface">test</div>
<div class="famous-surface">test</div>
</div>
</div>
這就是 ContainerSurface
主要的功能,將你的子元素包成一包,然後把這一包放到 DOM 裡面(或是另外給其他的模組使用。
Modifier 模組
modifiers/Draggable
modifiers/Fader
modifiers/ModifierChain
modifiers/StateModifier
首先先提一下 StateModifier
這個模組跟 Modifier
幾乎一樣,只是 Modifier
做的事情比 StateModifier
更多一些,所以其實可以把它看成是簡化版本的 Modifier
。它只能更動原有的屬性設定,如,size
, origin
, opacity
, transform
這四種而已。
Fader
則更輕巧,他所能做的事情只有將你的元素淡入或是淡出(預設是隱藏的
ModifierChain
則是可以把多種 Modifier
串起來,這樣你就不用一直使用 .add()
來新增了。
Draggable
目前可利用狀況不明,你可以套用,但是做不出任何效果,我已經寫信去問官方,有回覆會再來這邊更新。
在等待官方回覆的同時,我依照 EventHandler
的特性來思考這個 Modifier
,既然有 pipe
與 subscribe
可用,所以就嘗試了一下,後來官方也回信來,用法確實是需要使用 pipe
或是 subscribe
,實際範例如下,
define(function(require, exports, module) {
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Modifier = require('famous/core/Modifier');
var Transform = require('famous/core/Transform');
var Draggable = require('famous/modifiers/Draggable');
var ContainerSurface = require('famous/surfaces/ContainerSurface');
var mainContext = Engine.createContext();
var container = new ContainerSurface();
var surface, modifier, drag;
for (var i = 0; i < 5; i++) {
surface = new Surface({
size: [100, 100],
content: 'box '+ i,
properties: {
backgroundColor: "red"
}
});
modifier = new Modifier({
transform: Transform.translate( i * 110, 0, 0 )
});
drag = new Draggable();
// 使用 subscribe
drag.subscribe(surface);
// 或是使用 pipe
// surface.pipe(drag);
container.add(drag).add(modifier).add(surface);
}
mainContext.add(container);
});
當中有提及 subscribe
與 pipe
在此暫且不詳細說明,之後提及 EventHandler
的時候會再詳細說明。
Surface 新增模組
surfaces/FromContainerSurafce
surfaces/SubmitInputSurface
surfaces/TextareaSurface
大概就如同字面上的意思,跟 surfaces/InputSurface
類似,主要是表單與其元件的模組。使用的方式也跟 surfaces/InputSurface
雷同。
補充說明 ModifierChain
補充說明 ModifierChain
的使用方式,
define(function(require, exports, module) {
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Modifier = require('famous/core/Modifier');
var ModifierChain = require('famous/modifiers/ModifierChain');
var Transform = require('famous/core/Transform');
var mainContext = Engine.createContext();
var surface= new Surface({
size: [100, 100],
properties: {
backgroundColor: "red"
}
});
var modifierChain = new ModifierChain(
new Modifier({
origin: [0.5, 0.5],
transform: Transform.rotateZ( 45 * Math.PI / 180 )
}),
new Modifier({
transform: Transform.translate(100, 100, 0)
}),
new Modifier({
size: [200, 200]
}),
);
mainContext.add(modifierChain).add(surface);
});
小結
本文在我的 famous.tw 上面同步刊出。