Tuesday, October 6, 2015
Timbre demo from Famo.us University using Meteor.js and CoffeeScript
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/.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
Labels:
CoffeeScript,
Famo.us,
Meteor.js
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment