Introduction
As already demonstrated in my previous article
Famo.us polaroid tutorial in CoffeeScript and within Meteor ,
Meteor ,
CoffeeScript and
Famo.us are incredibly useful tools for front end or full stack developers. This article just show the same principles with the
Famo.us University Timbre tutorial . A live demo is deployed on Meteor's testing ground:
http://famoustimbre.meteor.com/ .
VIDEO
Show me the code, please
If you find yourself stuck at translating some JS concept to CoffeeScript while playing the nice tutorial from
Famo.us University , I provide my code hereafter:
client/stylesheets/app.styl
@import nib
html
font-family: Helvetica
*
-webkit-user-drag: none
body
-webkit-touch-callout: none
user-select: none
client/index.jade
head
title Famo.us Timbre
meta(name='viewport', content='width=device-width, maximum-scale=1, user-scalable=no')
meta(name='mobile-web-app-capable', content='yes')
meta(name='apple-mobile-web-app-capable', content='yes')
meta(name='apple-mobile-web-app-status-bar-style', content='black')
body
+index
template(name='index')
client/lib/famous.coffee
window.Famous ?= {}
client/lib/timbre.coffee
window.Timbre ?= {}
client/startup/famous.coffee
# Import Famous
require 'famous/core/famous'
# Adds the famo.us dependencies
require 'famous-polyfills'
# Wait for document ready
$(document).ready ->
# Load Famo.us libraries
Famous.Engine = require 'famous/core/Engine'
Famous.Surface = require 'famous/core/Surface'
Famous.Transform = require 'famous/core/Transform'
Famous.View = require 'famous/core/View'
Famous.Modifier = require 'famous/core/Modifier'
Famous.StateModifier = require 'famous/modifiers/StateModifier'
Famous.HeaderFooter = require 'famous/views/HeaderFooterLayout'
Famous.ImageSurface = require 'famous/surfaces/ImageSurface'
Famous.FastClick = require 'famous/inputs/FastClick'
Famous.GenericSync = require 'famous/inputs/GenericSync'
Famous.MouseSync = require 'famous/inputs/MouseSync'
Famous.TouchSync = require 'famous/inputs/TouchSync'
Famous.GenericSync.register
'mouse': Famous.MouseSync
'touch': Famous.TouchSync
Famous.Easing = require 'famous/transitions/Easing'
Famous.Transitionable = require 'famous/transitions/Transitionable'
Famous.Timer = require 'famous/utilities/Timer'
# Create main context
Timbre.mainCtx = Famous.Engine.createContext()
client/models/StripData.coffee
Timbre.StripData = [
{title: 'search', iconUrl: 'img/strip-icons/famous.png'}
{title: 'starred', iconUrl: 'img/strip-icons/starred.png'}
{title: 'friends', iconUrl: 'img/strip-icons/friends.png'}
{title: 'settings', iconUrl: 'img/strip-icons/settings.png'}
]
client/index.coffee
ASPECT_RATIO = 320 / 548
Template.index.rendered = ->
$document = $ document
$document.ready ->
docwidth = $document.width()
docheight = $document.height()
if docwidth / ASPECT_RATIO > docheight
screenwidth = docheight * ASPECT_RATIO
screenheight = docheight
else
screenwidth = docwidth
screenheight = docwidth / ASPECT_RATIO
appView = new Timbre.AppView()
mainMod = new Famous.Modifier
size: [screenwidth, screenheight]
Timbre.mainCtx
.add mainMod
.add appView
client/models/AppView.coffee
$(document).ready ->
class Timbre.AppView extends Famous.View
DEFAULT_OPTIONS:
openPosition: 276
transition:
duration: 300
curve: Famous.Easing.inOutBack
posThreshold: 138
velTreshold: 0.75
constructor: (@options) ->
@constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS
super @options
@menuToggle = false
@pageViewPos = new Famous.Transitionable 0
@createPageView()
@createMenuView()
@setListeners()
@handleSwipe()
createPageView: ->
@pageView = new Timbre.PageView()
@pageModifier = new Famous.Modifier
transform: =>
Famous.Transform.translate @pageViewPos.get(), 0, 0
@add(@pageModifier).add @pageView
createMenuView: ->
@menuView = new Timbre.MenuView stripData: Timbre.StripData
menuModifier = new Famous.StateModifier
transform: Famous.Transform.behind
@add(menuModifier).add @menuView
setListeners: ->
@pageView.on 'menuToggle', @toggleMenu
toggleMenu: =>
if @menuToggle
@slideLeft()
else
@slideRight()
@menuView.animateStrips()
@menuToggle = !@menuToggle
slideLeft: ->
@pageViewPos.set 0, @options.transition, =>
@menuToggle = false
slideRight: ->
@pageViewPos.set @options.openPosition, @options.transition, =>
@menuToggle = true
handleSwipe: ->
sync = new Famous.GenericSync(
['mouse', 'touch']
, {direction: Famous.GenericSync.DIRECTION_X}
)
@pageView.pipe sync
sync.on 'update', (data) =>
currentPosition = @pageViewPos.get()
@pageViewPos.set Math.max 0, currentPosition + data.delta
if currentPosition is 0 and data.velocity > 0
@menuView.animateStrips()
sync.on 'end', (data) =>
velocity = data.velocity
position = @pageViewPos.get()
if position > @options.posThreshold
if velocity < -@options.velTreshold
@slideLeft()
else
@slideRight()
else
if velocity > @options.velTreshold
@slideRight()
else
@slideLeft()
client/models/PageView.coffee
$(document).ready ->
class Timbre.PageView extends Famous.View
DEFAULT_OPTIONS:
headerSize: 44
constructor: (@options) ->
@constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS
super @options
@createLayout()
@createHeader()
@createBody()
@setListeners()
createLayout: ->
@layout = new Famous.HeaderFooter
headerSize: @options.headerSize
layoutModifier = new Famous.StateModifier
transform: Famous.Transform.translate 0, 0, .1
@add(layoutModifier).add @layout
createHeader: ->
backgroundSurface = new Famous.Surface
properties: backgroundColor: 'black'
backgroundModifier = new Famous.StateModifier
transform: Famous.Transform.behind
@layout.header
.add backgroundModifier
.add backgroundSurface
@hamburgerSurface = new Famous.ImageSurface
size: [44, 44]
content: 'img/hamburger.png'
searchSurface = new Famous.ImageSurface
size: [232, 44]
content: 'img/search.png'
iconSurface = new Famous.ImageSurface
size: [44, 44]
content: 'img/icon.png'
hamburgerModifier = new Famous.StateModifier
origin: [0, .5]
align: [0, .5]
searchModifier = new Famous.StateModifier
origin: [.5, .5]
align: [.5, .5]
iconModifier = new Famous.StateModifier
origin: [1, .5]
align: [1, .5]
@layout.header
.add hamburgerModifier
.add @hamburgerSurface
@layout.header
.add searchModifier
.add searchSurface
@layout.header
.add iconModifier
.add iconSurface
createBody: ->
@bodySurface = new Famous.ImageSurface
size: [undefined, true]
content: 'img/body.png'
@layout.content.add @bodySurface
setListeners: ->
@hamburgerSurface.on 'click', =>
@_eventOutput.emit 'menuToggle'
@bodySurface.pipe @_eventOutput
createBacking: ->
backing = new Famous.Surface
properties:
backgroundColor: 'black'
boxShadow: '0 0 20px rgba(0,0,0,0.5)'
@add backing
client/models/MenuView.coffee
$(document).ready ->
class Timbre.PageView extends Famous.View
DEFAULT_OPTIONS:
headerSize: 44
constructor: (@options) ->
@constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS
super @options
@createLayout()
@createHeader()
@createBody()
@setListeners()
createLayout: ->
@layout = new Famous.HeaderFooter
headerSize: @options.headerSize
layoutModifier = new Famous.StateModifier
transform: Famous.Transform.translate 0, 0, .1
@add(layoutModifier).add @layout
createHeader: ->
backgroundSurface = new Famous.Surface
properties: backgroundColor: 'black'
backgroundModifier = new Famous.StateModifier
transform: Famous.Transform.behind
@layout.header
.add backgroundModifier
.add backgroundSurface
@hamburgerSurface = new Famous.ImageSurface
size: [44, 44]
content: 'img/hamburger.png'
searchSurface = new Famous.ImageSurface
size: [232, 44]
content: 'img/search.png'
iconSurface = new Famous.ImageSurface
size: [44, 44]
content: 'img/icon.png'
hamburgerModifier = new Famous.StateModifier
origin: [0, .5]
align: [0, .5]
searchModifier = new Famous.StateModifier
origin: [.5, .5]
align: [.5, .5]
iconModifier = new Famous.StateModifier
origin: [1, .5]
align: [1, .5]
@layout.header
.add hamburgerModifier
.add @hamburgerSurface
@layout.header
.add searchModifier
.add searchSurface
@layout.header
.add iconModifier
.add iconSurface
createBody: ->
@bodySurface = new Famous.ImageSurface
size: [undefined, true]
content: 'img/body.png'
@layout.content.add @bodySurface
setListeners: ->
@hamburgerSurface.on 'click', =>
@_eventOutput.emit 'menuToggle'
@bodySurface.pipe @_eventOutput
createBacking: ->
backing = new Famous.Surface
properties:
backgroundColor: 'black'
boxShadow: '0 0 20px rgba(0,0,0,0.5)'
@add backing
client/models/StripView.coffee
$(document).ready ->
class Timbre.StripView extends Famous.View
DEFAULT_OPTIONS:
width: 320
height: 55
angle: -0.2
iconSize: 32
iconUrl: 'img/strip-icons/famous.png'
title: 'Famo.us'
fontSize: 26
constructor: (@options) ->
@constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS
super @options
@createBackground()
@createIcon()
@createTitle()
createBackground: ->
backgroundSurface = new Famous.Surface
size: [@options.width, @options.height]
properties:
backgroundColor: 'black'
boxShadow: '0 0 1px rgba(0, 0, 0, 1)'
rotateModifier = new Famous.StateModifier
transform: Famous.Transform.rotateZ @options.angle
skewModifier = new Famous.StateModifier
transform: Famous.Transform.skew 0, 0, @options.angle
@add(rotateModifier)
.add skewModifier
.add backgroundSurface
createIcon: ->
iconSurface = new Famous.ImageSurface
size: [@options.iconSize, @options.iconSize]
content: @options.iconUrl
properties:
pointerEvents: 'none'
iconModifier = new Famous.StateModifier
transform: Famous.Transform.translate 24, 2, 0
@add(iconModifier).add iconSurface
createTitle: ->
titleSurface = new Famous.Surface
size: [true, true]
content: @options.title
properties:
color: 'white'
fontSize: "#{@options.fontSize}px"
textTransform: 'uppercase'
pointerEvents: 'none'
titleModifier = new Famous.StateModifier
transform: Famous.Transform.thenMove(
Famous.Transform.rotateZ @options.angle
, [75, -5, 0]
)
@add(titleModifier).add titleSurface
Aucun commentaire:
Enregistrer un commentaire